package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.business.rule.RuleBusinessLogger;
import com.xbongbong.paas.constant.ConfigConstant;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.SaasParticularAttributePoJo;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.ButtonPojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.ProductFieldPojo;
import com.xbongbong.paas.pojo.WorkFlowPojo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.FormDataGetVO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.team.TeamDataHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.businessproduct.pojo.dto.BusinessProductListDTO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.contract.pojo.dto.ContractUpdateBatchDTO;
import com.xbongbong.pro.contract.pojo.dto.ContractUpdateDTO;
import com.xbongbong.pro.customer.pojo.dto.ChangeStatusDTO;
import com.xbongbong.pro.detailtab.dto.ChangeDocumentStatusSaveDTO;
import com.xbongbong.pro.detailtab.pojo.OneKeyProduceProductPojo;
import com.xbongbong.pro.detailtab.vo.ChangeDocumentStatusSaveVO;
import com.xbongbong.pro.detailtab.vo.ProductSummaryVO;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.ReceiveStatusEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.PaymentErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.PurchaseErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.TemplateErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.UserTeamErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.AfterSavePojo;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainBatchLinkItemDTO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainInLinkItemDTO;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.log.pojo.dto.RuleBusinessLogDTO;
import com.xbongbong.pro.message.constant.InstockPushConstant;
import com.xbongbong.pro.message.constant.PurchasePushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.payplan.pojo.dto.PayPlanDeleteBatchDTO;
import com.xbongbong.pro.product.pojo.ProductSavePojo;
import com.xbongbong.pro.product.pojo.dto.PagingProductDTO;
import com.xbongbong.pro.product.pojo.vo.DetailProductVO;
import com.xbongbong.pro.product.pojo.vo.PagingProductVO;
import com.xbongbong.pro.purchase.pojo.dto.PurchaseDeleteBatchDTO;
import com.xbongbong.pro.purchase.pojo.dto.PurchaseEditAttrUpdateDTO;
import com.xbongbong.pro.purchase.pojo.dto.PurchaseListDTO;
import com.xbongbong.pro.purchase.pojo.dto.PurchaseUpdateBatchDTO;
import com.xbongbong.pro.purchase.pojo.dto.PurchaseUpdateByBusinessRuleDTO;
import com.xbongbong.pro.purchase.pojo.dto.PurchaseUpdateDTO;
import com.xbongbong.pro.purchase.pojo.vo.PurchaseDeleteBatchVO;
import com.xbongbong.pro.purchase.pojo.vo.PurchaseListVO;
import com.xbongbong.pro.purchase.pojo.vo.PurchaseUpdateBatchVO;
import com.xbongbong.pro.purchaseproduct.pojo.dto.PurchaseProductDeleteBatchDTO;
import com.xbongbong.pro.pushnotify.dto.PushNotifyDeleteDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.service.toolbox.elasticsearch.help.ProEsHelper;
import com.xbongbong.pro.service.toolbox.statistic.help.FormHelp;
import com.xbongbong.pro.sheet.pojo.dto.SheetDeleteHandleRelateDTO;
import com.xbongbong.pro.suppliercommunicate.pojo.dto.SupplierDynamicAddDTO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.weblist.pojo.WaitOutstockProductPojo;
import com.xbongbong.saas.analytical.impl.PurchaseValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.MultiUnitConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.PurchaseBalanceEntity;
import com.xbongbong.saas.domain.entity.PurchaseInvoiceRelationshipEntity;
import com.xbongbong.saas.domain.entity.PurchaseProductEntity;
import com.xbongbong.saas.domain.entity.SmartReplenishmentEntity;
import com.xbongbong.saas.domain.entity.SupplierProductEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.PurchaseEntityExt;
import com.xbongbong.saas.domain.entity.ext.SupplierEntityExt;
import com.xbongbong.saas.enums.ContractProductTypeEnum;
import com.xbongbong.saas.enums.FormConfigEnum;
import com.xbongbong.saas.enums.InOutStockStatusEnum;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperatePageEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.UpdateDataTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.PaySheetEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.PurchaseInstockEnum;
import com.xbongbong.saas.enums.business.PurchaseInvoiceEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseEnum;
import com.xbongbong.saas.enums.business.SupplierEnum;
import com.xbongbong.saas.enums.business.WaitInstockEnum;
import com.xbongbong.saas.enums.dictionary.AllInBoundEnum;
import com.xbongbong.saas.enums.dictionary.EnableButtonEnum;
import com.xbongbong.saas.enums.product.ContractProductEnum;
import com.xbongbong.saas.enums.product.PurchaseProductEnum;
import com.xbongbong.saas.help.ExplainHelp;
import com.xbongbong.saas.help.FundHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.ProDetailHandlerHelp;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.help.SaasDeleteHelp;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.help.SaasGetHelp;
import com.xbongbong.saas.help.SaasListHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.help.workflow.PurchaseHelp;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.PurchaseBalanceModel;
import com.xbongbong.saas.model.PurchaseInvoiceRelationshipModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.PurchaseProductModel;
import com.xbongbong.saas.model.PurchaseUserModel;
import com.xbongbong.saas.model.SmartReplenishmentModel;
import com.xbongbong.saas.model.SupplierModel;
import com.xbongbong.saas.model.SupplierProductModel;
import com.xbongbong.saas.service.ContractService;
import com.xbongbong.saas.service.InstockService;
import com.xbongbong.saas.service.MobileDetailService;
import com.xbongbong.saas.service.PayPlanService;
import com.xbongbong.saas.service.ProductService;
import com.xbongbong.saas.service.PurchaseProductService;
import com.xbongbong.saas.service.PurchaseService;
import com.xbongbong.saas.service.PushNotifyService;
import com.xbongbong.saas.service.SupplierCommunicateService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.service.WaitPurchaseService;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.saas.enums.RelativeProductEnum.PRODUCT_PRICE;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 采购合同service实现层
 * @author WangJian
 * @date  2019-01-23 20:02
 * @since v1.0
 * @version v1.0
 **/
@Service("PurchaseService")
public class PurchaseServiceImpl implements PurchaseService {

    private static final Logger LOG = LoggerFactory.getLogger(PurchaseServiceImpl.class);

    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private ExplainHelp explainHelp;
    @Resource
    private SaasGetHelp saasGetHelp;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private UserModel userModel;
    @Resource
    private InstockService instockService;
    @Resource
    private PurchaseProductModel purchaseProductModel;
    @Resource
    private ProductModel productModel;
    @Resource
    private InstockModel instockModel;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private ProductService productService;
    @Resource
    private PayPlanService payPlanService;
    @Resource
    private EsHelper esHelper;
    @Resource
    private PurchaseProductService purchaseProductService;
    @Resource
    private ContractService contractService;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private SupplierModel supplierModel;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private PushNotifyService pushNotifyService;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    @Lazy
    private RuleBusinessLogger ruleBusinessLogger;
    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;
    @Resource
    private SupplierProductModel supplierProductModel;
    @Resource
    private SaasFormHelp saasFormHelp;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private MobileDetailService mobileDetailService;
    @Resource
    private ProDetailHandlerHelp proDetailHandlerHelp;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private FormHelp formHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PurchaseInvoiceRelationshipModel purchaseInvoiceRelationshipModel;
    @Resource
    private ProEsHelper proEsHelper;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private SupplierCommunicateService supplierCommunicateService;
    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private LogHandleHelp logHandleHelp;
    @Resource
    private ContractModel contractModel;
    @Resource
    private PurchaseBalanceModel purchaseBalanceModel;
    @Resource
    private SaasListHelp saasListHelp;
    @Resource
    private PurchaseValidateAnalyticalServiceImpl purchaseAnalyticalService;
    @Resource
    private PurchaseHelp purchaseHelp;
    @Resource
    private PurchaseUserModel purchaseUserModel;
    @Resource
    private SmartReplenishmentModel smartReplenishmentModel;
    @Resource
    private WaitPurchaseService waitPurchaseService;
    @Resource
    private TeamDataHelp teamDataHelp;
    @Resource
    private UserTeamHelp userTeamHelp;

    private final static int PURCHASE_NAME_MAX = 50;



    /**
     * 采购合同保存前saas特殊校验
     *
     * @param validateDataDTO saas特殊校验数据入参
     * @author Jian.Wang
     * @date 2019/1/23 20:00
     * @since v1.0
     **/
    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        purchaseAnalyticalService.beforeSave(validateDataDTO);
    }



    /**
     * 供应商产品校验
     * @param purchaseId
     * @param productList
     * @param corpid
     * @param supplierId
     * @return
     * @throws XbbException
     */
    private boolean validateProductDemo(Long purchaseId, JSONArray productList, String corpid, Long supplierId, Long formId) throws XbbException {
        boolean isNew = Objects.isNull(purchaseId);
        if (isNew && (Objects.isNull(productList) || productList.isEmpty())){
            return true;
        }
        Set<Long> pageProductIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (Object obj : productList){
            JSONObject json = JSONObject.parseObject(obj.toString());
            Long productId = json.getLong(SelectProductEnum.PRODUCT.getAttr());
            pageProductIds.add(productId);
        }
        //判断产品合法
        Map<Long,String> pageProductMap = formDataValidateProductHelp.productExitContract(productList,corpid,new ArrayList<>(pageProductIds));

        // 避免导入时导入非此供应商的关联产品
        boolean isPurchaseProductMustBelongSupplier = false;
        FormConfigEntity formConfigEntity = formConfigModel.getEntityByFormId(corpid, formId, FormConfigEnum.PURCHASE_PRODUCT_MUST_BELONG_SUPPLIER.getConfig());
        if (Objects.isNull(formConfigEntity)){
            isPurchaseProductMustBelongSupplier = Objects.equals(FormConfigEnum.PURCHASE_PRODUCT_MUST_BELONG_SUPPLIER.getConfigValue(),BasicConstant.IS_USE.toString());
        } else if (Objects.equals(formConfigEntity.getConfigValue(), BasicConstant.IS_USE.toString())) {
            isPurchaseProductMustBelongSupplier = true;
        }
        if (isPurchaseProductMustBelongSupplier) {
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid",corpid);
            param.put("del",0);
            param.put("supplierId",supplierId);
            param.put("productIdIn",pageProductIds);
            List<SupplierProductEntity> supplierProductEntityList = supplierProductModel.findEntitys(param);
            supplierProductEntityList.forEach(item -> pageProductIds.remove(item.getProductId()));
            if (!pageProductIds.isEmpty()){
                throw new XbbException(PurchaseErrorCodeEnum.API_ERROR_225022);
            }
        }

        boolean allIncoming = false;
        if (!isNew) {
            // 获取下游采购入库单的产品
            Map<String, Double> businessProductMap = formDataValidateProductHelp.getInstockProduct(corpid, purchaseId, InstockTypeEnum.PURCHASE_INSTOCK.getCode(), pageProductMap);
            boolean haveCorresponding = false;
            for (String s : businessProductMap.keySet()) {
                if (s.contains("_")) {
                    haveCorresponding = true;
                    break;
                }
            }
            boolean needMerge = !businessProductMap.isEmpty() && !haveCorresponding;
            Map<String, Double> productNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (Object obj : productList) {
                JSONObject json = (JSONObject) obj;
                Long productId = json.getLong(SelectProductEnum.PRODUCT.getAttr());
                // PRODUCT_SUB_ID是编辑的时候传给前段的采购合同产品的主键id，保存的时候前端传回来！！
                Long productSubId = json.getLong(BusinessConstant.PRODUCT_SUB_ID);
                String key;
                if (needMerge) {
                    key = productId.toString();
                } else {
                    key = productId + "_" + productSubId;
                }
                Double productNum = json.getDouble(SelectProductEnum.NUM.getAttr());
                Double num = productNumMap.getOrDefault(key, 0D);
                num = Arith.add(num, productNum);
                productNumMap.put(key, num);
            }
            allIncoming = formDataValidateProductHelp.upstreamDocumentsProductNumLegalCheck(false, businessProductMap, productNumMap, pageProductMap, I18nMessageUtil.getMessage(I18nStringConstant.LESS_STOCK_NUM));
        }
        return allIncoming;
    }


    /**
     * 采购合同保存后逻辑
     *
     * @param saasFormSaveDTO saas保存数据
     * @author Jian.Wang
     * @date 2019/1/23 20:00
     * @since v1.0
     **/
    @Override
    public AfterSavePojo afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        AfterSavePojo afterSavePojo = new AfterSavePojo();
        String corpid = saasFormSaveDTO.getCorpid();
        JSONObject newData = saasFormSaveDTO.getNewData();
        PaasFormDataEntity paasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long dataId = paasFormDataEntity.getId();

        // 团队保存
        afterSavePojo = teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), dataId, paasFormDataEntity, saasFormSaveDTO.getIsImport(), false);
        //        userTeamService.saveUserTeam(saasFormSaveDTO);


        PurchaseEntityExt purchaseEntityExt = new PurchaseEntityExt();
        BeanUtil.copyProperties(paasFormDataEntity, purchaseEntityExt);
        Integer taskType = saasFormSaveDTO.getTaskType();

        Runnable runnable = () -> {
            try {
                // 保存要处理的关联产品和采购合同入库信息
                if (saasFormSaveDTO.getIsNew() || saasFormSaveDTO.getSaasNeedRedundantAttrPoJo().getAttrCanSee(PurchaseEnum.PRODUCT.getAttr())) {
                    dealWithPurchaseProduct(purchaseEntityExt, saasFormSaveDTO.getIsNew(),taskType);
                }
            } catch (Exception e) {
                LOG.error("采购合同保存产品数据解析/采购合同保存产品关联产品", e);
            }
            //新建采购合同 添加项目日志
            Boolean isNew = saasFormSaveDTO.getIsNew();
            if(isNew){
                try {
                    String creatorId = paasFormDataEntity.getCreatorId();
                    //如果是审批通过后的新建， loginUser 拿到的不是创建人，需要根据 creatorId 再查一下
                    UserEntity userEntity = userModel.getByKey(creatorId, corpid);
                    Integer isImport = saasFormSaveDTO.getIsImport();
                    Long newSupplierId = FastJsonHelper.getLongFromFormData(newData, PurchaseEnum.SUPPLIER_ID.getAttr());
                    String operate = Objects.equals(isImport, 1) ? I18nMessageUtil.getMessage(I18nStringConstant.IMPORTED) : I18nMessageUtil.getMessage(I18nStringConstant.ADD);
                    String communicateMemo = Objects.isNull(userEntity) ? "" : userEntity.getName()  + operate + I18nMessageUtil.getMessage(CommonConstant.PURCHASE) + " :" + paasFormDataEntity.getSerialNo();
                    String log = I18nMessageUtil.getMessage(I18nStringConstant.PURCHASE_CREATE_LOG);
                    projectLog(saasFormSaveDTO, creatorId, newSupplierId, communicateMemo, log);
                } catch (XbbException e) {
                    LOG.error("采购合同项目日志记录失败",e);
                }
            }

            try {
                if (!Objects.equals(saasFormSaveDTO.getIsImport(), 1)) {
                    // 采购完成提醒入库 待入库消息推送
                    Integer allIncoming = getIntegerOrDefaultFromFormData(saasFormSaveDTO.getNewData(), PurchaseEnum.ALL_INCOMING.getAttr(), 0);
                    if (!Objects.equals(allIncoming, 1)) {
                        // 推送给仓库主管 系统默认仓库主管roleId=22?
                        List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(22));
                        List<String> userIdList = new ArrayList<>();
                        for (UserEntity manager : managers) {
                            userIdList.add(manager.getUserId());
                        }
                        PushRefTypePojo.Options options = new PushRefTypePojo.Options(paasFormDataEntity.getAppId(), paasFormDataEntity.getMenuId(), paasFormDataEntity.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(),
                                saasFormSaveDTO.getBusinessType(), saasFormSaveDTO.getSubBusinessType());
                        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0, null, I18nMessageUtil.getMessage(InstockPushConstant.INSTOCK_TITLE), String.format(I18nMessageUtil.getMessage(InstockPushConstant.WAIT_INSTOCK_CONTENT), paasFormDataEntity.getSerialNo()), null, options);
                        baseProducer.sendMessage(PushTypeEnum.WAIT_INSTOCK_PUSH, messageRabbitMqDTO);
                    }

                    // 采购完成提醒采购主管 采购成功消息推送 系统默认采购主管roleId=21?
                    List<UserEntity> managers = userModel.getUsersByRoleId(corpid, Collections.singletonList(21));
                    List<String> userIdList = new ArrayList<>();
                    for (UserEntity manager : managers) {
                        userIdList.add(manager.getUserId());
                    }
                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(paasFormDataEntity.getAppId(), paasFormDataEntity.getMenuId(),
                            paasFormDataEntity.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(),
                            saasFormSaveDTO.getBusinessType(), saasFormSaveDTO.getSubBusinessType());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, userIdList, Collections.singletonList(dataId), 0,
                            null, I18nMessageUtil.getMessage(PurchasePushConstant.PURCHASE_TITLE), String.format(I18nMessageUtil.getMessage(PurchasePushConstant.PURCHASE_SUCCESS_CONTENT),
                            paasFormDataEntity.getSerialNo()), null, options);
                    baseProducer.sendMessage(PushTypeEnum.PURCHASE_SUCCESS_PUSH, messageRabbitMqDTO);
                }
            } catch (Exception e) {
                LOG.error("采购完成提醒入库/采购完成提醒采购主管", e);
            }
        };
        threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
        return afterSavePojo;
    }

    private void projectLog(SaasFormSaveDTO saasFormSaveDTO, String creatorId, Long newSupplierId, String communicateMemo, String log) {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        JSONObject newData = saasFormSaveDTO.getNewData();
        String corpid = newPaasFormDataEntity.getCorpid();
        Long purchaseId = newPaasFormDataEntity.getId();
        //拼装
        try {
            SupplierDynamicAddDTO supplierDynamicAddDTO = new SupplierDynamicAddDTO();
            String supplierName = newData.getString(PurchaseEnum.SUPPLIER_ID_LINKED_TEXT.getAttr());
            supplierDynamicAddDTO.setCorpid(corpid);
            supplierDynamicAddDTO.setUserId(creatorId);
            supplierDynamicAddDTO.setSupplierId(newSupplierId);
            supplierDynamicAddDTO.setSupplierName(supplierName);
            supplierDynamicAddDTO.setMemo(communicateMemo);
            supplierDynamicAddDTO.setCommunicateBusinessText(newPaasFormDataEntity.getSerialNo());
            supplierDynamicAddDTO.setCommunicateBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
            supplierDynamicAddDTO.setDataId(purchaseId);
            supplierCommunicateService.addSupplierDynamic(supplierDynamicAddDTO);
        } catch (Exception e) {
            LOG.error(log, e);
        }
    }


    /**
     * 获取采购合同产品
     *
     * @param businessProductListDTO 入参
     * @param dataList data对象
     * @author chaoxiong.lei
     * @Date 14:37 2019/3/5
     * @since v1.0
     * @return BusinessProductListVO，属性product包含了单据关联产品，返回给前端的格式
     **/
   /* @Override
    public BusinessProductListVO getPurchaseProductList(BusinessProductListDTO businessProductListDTO, JSONObject dataList) throws XbbException {
        // 获取参数
        String corpid = businessProductListDTO.getCorpid();
        String userId = businessProductListDTO.getUserId();
        UserEntity userEntity = userModel.getByKey(userId, corpid);
        Integer businessType = businessProductListDTO.getBusinessType();
        Integer sourceBusinessType = businessProductListDTO.getSourceBusinessType();
        Long purchaseId = businessProductListDTO.getDataId();
        boolean detailGet = businessProductListDTO.getDetailGet();
        Boolean formLinkAdd = businessProductListDTO.getForLinkAdd();
        Long instockId = businessProductListDTO.getInstockId();
        PurchaseEntityExt purchaseEntityExt;

        boolean isInstock = Objects.equals(sourceBusinessType, XbbRefTypeEnum.INSTOCK.getCode());
        boolean isReturnedPurchase = Objects.equals(sourceBusinessType, XbbRefTypeEnum.RETURNED_PURCHASE.getCode());
        boolean generalGetPurchaseProduct = !isInstock && !isReturnedPurchase;

        List<PurchaseProductEntity> purchaseProductEntityList = new ArrayList<>();
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, corpid);
        modelMap.put("purchaseSheetId", purchaseId);
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put(ParameterConstant.PAGE, businessProductListDTO.getPage());
        PageHelper pageHelper = PageHelperUtil.getPageHelper(modelMap, purchaseProductModel, businessProductListDTO.getPageSize());
        if (businessProductListDTO.getForProcess()) {
            purchaseEntityExt = new PurchaseEntityExt();
            JSONObject productObject =  saasUpdateHelp.getJsonObjectOrDefaultFromFormData(dataList, PurchaseEnum.PRODUCT.getAttr(), new JSONObject());
            JSONArray productArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(productObject, StringConstant.PRODUCT_LIST, new JSONArray());
            Map<Long, ProductEntityExt> productMap = getProductMap(corpid, productArray);
            getProductList(businessProductListDTO.getForLinkAdd(), corpid, purchaseProductEntityList, productObject, productMap);
        } else {
            purchaseEntityExt = purchaseModel.getByKey(purchaseId, corpid);
            if (purchaseEntityExt == null) {
                throw new XbbException(PurchaseErrorCodeEnum.API_ERROR_225006);
            }
            if (isInstock) {
                // 获取采购合同剩余未入库产品信息及数量
                List<Long> instockIdList = null;
                if (instockId != null && instockId != 0L) {
                    instockIdList = new ArrayList<>();
                    instockIdList.add(instockId);
                }
                purchaseProductEntityList = getSurplusProduct(corpid, purchaseId, purchaseEntityExt, instockIdList);

                if (instockId == null || instockId == 0L) {
                    if (purchaseProductEntityList.isEmpty()) {
                        // 剩余未入库的产品为空 代表入库完毕
                        JSONObject purchaseData = purchaseEntityExt.getData();
                        purchaseData.put(PurchaseEnum.ALL_INCOMING.getAttr(), 1);
                        purchaseEntityExt.setData(purchaseData);
                        purchaseModel.update(purchaseEntityExt);
                        throw new XbbException(PurchaseErrorCodeEnum.API_ERROR_225032);
                    }
                }
            }
            if (isReturnedPurchase) {
                // 采购退货单获取采购合同已入库产品
                purchaseProductEntityList = getAlreadyStoreProduct(corpid, purchaseId);
            }
            if (generalGetPurchaseProduct) {
                // 拿到采购合同的所有产品
                purchaseProductEntityList = (List<PurchaseProductEntity>) PageHelperUtil.getEntityList(modelMap, pageHelper, purchaseProductModel);
                List<Long> productIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (PurchaseProductEntity entity : purchaseProductEntityList) {
                    productIdIn.add(entity.getProductId());
                }
                if (!productIdIn.isEmpty()) {
                    Map<Long, ProductEntityExt> productMap = productModel.getProductMapByIdIn(corpid, productIdIn, null);
                    for (PurchaseProductEntity entity : purchaseProductEntityList) {
                        ProductEntityExt product = productMap.get(entity.getProductId());
                        if (product == null) {
                            continue;
                        }
                        JSONObject productData = product.getData();
                        if (null != productData) {
                            entity.setBarcode(productData.getString(ProductEnum.BARCODE.getAttr()));
                        }
                    }
                }
            }
        }

        Set<Long> productIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        productIds.add(-1L);
        purchaseProductEntityList.forEach(item -> productIds.add(item.getProductId()));

        // 根据productIdIn获取对应产品信息
        Map<Long, PaasFormDataEntityExt> productMap = productService.getProductMapByIdIn(productIds,corpid,  null);

        // 用于存放当前启用的产品模板解释的map
        Map<String, FieldAttrEntity> nowProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        saasAddHelp.getRelativeProductExplainsFromDB(corpid, nowProductExplainMap, null);

        // 返回给前端的接受对象
        JSONObject productFinalObj = new JSONObject();
        JSONArray productArray = new JSONArray();
        Map<Integer, JSONObject> productSortMap = new TreeMap<>();
        BusinessProductListVO businessProductListVO = new BusinessProductListVO();
        // 与productList同级，返回对应关联产品的attr
        String attrStr = "";

        if (isInstock) {
            attrStr = InstockEnum.PRODUCT.getAttr();
            for (PurchaseProductEntity purchaseProduct : purchaseProductEntityList) {
                Long productId = purchaseProduct.getProductId();
                PaasFormDataEntityExt product = productMap.get(productId);
                if (product == null) {
                    continue;
                }

                InstockProductEntityExt instockProductEntityExt = new InstockProductEntityExt();
                BeanUtil.copyProperties(purchaseProduct, instockProductEntityExt);
                // 获取菜头合同关联产品的采购价作为入库成本
                instockProductEntityExt.setCost(purchaseProduct.getProductPrice());
                instockProductEntityExt.setStock(product.getData().getDouble(ProductEnum.STOCK.getAttr()));
                if (product.getData() != null) {
                    JSONArray imageArray = product.getData().getJSONArray(ProductEnum.PRODUCT_IMGS.getAttr());
                    instockProductEntityExt.setImageUrlArray(imageArray);
                }
                FormatInstockProductDTO formatInstockProductDTO = new FormatInstockProductDTO();
                BeanUtil.copyProperties(businessProductListDTO, formatInstockProductDTO);
                formatInstockProductDTO.setNowProductExplainMap(nowProductExplainMap);

                // 采购合同的产品备注回显到入库单产品的备注
                ProductStockInfoEntity productStockInfo = new ProductStockInfoEntity();
                productStockInfo.setMemo(purchaseProduct.getMemo());
                instockProductEntityExt.setProductStockInfoEntity(productStockInfo);
                formatInstockProductDTO.setInstockProductExt(instockProductEntityExt);
                formatInstockProductDTO.setUserEntity(userEntity);
                formatInstockProductDTO.setSourceBusinessType(businessProductListDTO.getBusinessType());
                JSONObject productObj = instockService.getFormatProductJsonArray(formatInstockProductDTO);

                productSortMap.put(purchaseProduct.getSort(), productObj);
            }
        }
        if (isReturnedPurchase) {
            BusinessProductEnum businessProductEnum = BusinessProductEnum.getByCode(XbbRefTypeEnum.RETURNED_PURCHASE.getCode());
            attrStr = ReturnedPurchaseEnum.PRODUCTS.getAttr();
            for (PurchaseProductEntity purchaseProduct : purchaseProductEntityList) {
                Long productId = purchaseProduct.getProductId();
                PaasFormDataEntityExt product = productMap.get(productId);
                if (product == null) {
                    continue;
                }

                FormatRelativeProductEntityExt formatProduct = new FormatRelativeProductEntityExt();
                BeanUtil.copyProperties(purchaseProduct, formatProduct);
                // 获取采购合同关联产品的采购价作为入库成本
                formatProduct.setCost(purchaseProduct.getProductPrice());
                if (product.getData() != null) {
                    JSONArray imageArray = product.getData().getJSONArray(ProductEnum.PRODUCT_IMGS.getAttr());
                    if (Objects.nonNull(imageArray) && !imageArray.isEmpty()) {
                        formatProduct.setImageUrl(imageArray.getString(imageArray.size()-1));
                    }
                }
                FormatRelativeProductDTO formatRelativeProductDTO = new FormatRelativeProductDTO();
                BeanUtil.copyProperties(businessProductListDTO, formatRelativeProductDTO);
                formatProduct.setRefId(purchaseId);
                formatRelativeProductDTO.setBusinessType(XbbRefTypeEnum.RETURNED_PURCHASE.getCode());
                formatRelativeProductDTO.setTargetBusinessType(businessProductListDTO.getBusinessType());
                formatRelativeProductDTO.setCorpid(corpid);
                formatRelativeProductDTO.setNowProductExplainMap(nowProductExplainMap);
                formatRelativeProductDTO.setFormatRelativeProductEntityExt(formatProduct);
                formatRelativeProductDTO.setUserEntity(userEntity);
                JSONObject productObj = productService.getFormatProductJsonArray(formatRelativeProductDTO);

                // 将数据的顺序和解释的顺序保持一致
                JSONArray attrArray = productObj.getJSONArray(StringConstant.RESULT);
                JSONArray sortedAttrArray = new JSONArray();
                for (RelativeProductEnum attrEnum : businessProductEnum.getList()) {
                    String saasAttr = attrEnum.getSaasAttr();
                    attrArray.forEach(item -> {
                        JSONObject itemObj = (JSONObject) item;
                        if (Objects.equals(itemObj.getString("attr"), saasAttr)) {
                            sortedAttrArray.add(item);
                        }
                    });
                }
                productObj.put(StringConstant.RESULT, sortedAttrArray);

                productSortMap.put(purchaseProduct.getSort(), productObj);
            }
        }
        // 获取采购合同解释
        Map<String, FieldAttrEntity> fieldAttrMap = paasFormExplainService.getFieldAttrMapByBusinessType(businessType, corpid);
        double totalProductMoney = 0D;
        if (generalGetPurchaseProduct) {
            attrStr = PurchaseEnum.PRODUCT.getAttr();
            for (PurchaseProductEntity purchaseProduct : purchaseProductEntityList) {
                Long productId = purchaseProduct.getProductId();
                PaasFormDataEntityExt product = productMap.get(productId);
                if (product == null) {
                    continue;
                }
                double num = purchaseProduct.getProductNum();
                double productPrice = purchaseProduct.getProductPrice() == null ? 0D : purchaseProduct.getProductPrice();
                // 小计
                double subtotal = Arith.mul(num, productPrice);
                totalProductMoney = Arith.add(totalProductMoney, subtotal);

                FormatRelativeProductEntityExt formatProduct = new FormatRelativeProductEntityExt();
                BeanUtil.copyProperties(purchaseProduct, formatProduct);
                // 获取菜头合同关联产品的采购价作为入库成本
                // 国军老哥说产品没有负责人，不用传ownerId
                HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
                BeanUtil.copyProperties(businessProductListDTO, handlerExplainDTO);
                handlerExplainDTO.setCreatorId(product.getCreatorId());
                boolean isPriceFieldNeedHide = ExplainUtil.isFieldNeedHide(nowProductExplainMap.getOrDefault(ProductEnum.PRICE.getSaasAttr(), new FieldAttrEntity()), handlerExplainDTO);
                // 流程不判断高级权限 18336
                if (isPriceFieldNeedHide && (!businessProductListDTO.getForProcess() || (Objects.nonNull(formLinkAdd) && formLinkAdd))) {
                    // 一键采购时产品成本不可见时采购单价置为0,有权限hidePrice控制，设置了没有用
                    formatProduct.setProductPrice(0D);

                }
                formatProduct.setCost(purchaseProduct.getProductPrice());
                String subTotalStr = attrDecimalPrecisionHelper.formatMoneyPrecision(subtotal, fieldAttrMap, PurchaseEnum.TOTAL_MONEY.getAttr());
                formatProduct.setSubTotal(subtotal);
                formatProduct.setSubTotalStr(subTotalStr);
                if (product.getData() != null) {
                    JSONArray imageArray = product.getData().getJSONArray(ProductEnum.PRODUCT_IMGS.getAttr());
                    if (Objects.nonNull(imageArray) && !imageArray.isEmpty()) {
                        formatProduct.setImageUrl(imageArray.getString(0));
                    }
                }
                FormatRelativeProductDTO formatRelativeProductDTO = new FormatRelativeProductDTO();
                BeanUtil.copyProperties(businessProductListDTO, formatRelativeProductDTO);
                formatRelativeProductDTO.setBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
                formatRelativeProductDTO.setTargetBusinessType(businessProductListDTO.getBusinessType());
                formatRelativeProductDTO.setCorpid(corpid);
                formatRelativeProductDTO.setNowProductExplainMap(nowProductExplainMap);
                formatRelativeProductDTO.setFormatRelativeProductEntityExt(formatProduct);
                formatRelativeProductDTO.setUserEntity(userEntity);
                JSONObject productObj = productService.getFormatProductJsonArray(formatRelativeProductDTO);

                productSortMap.put(purchaseProduct.getSort(), productObj);
            }
            // 详情页获取产品时需要返回解释
            if (detailGet) {
                productFinalObj.put(BusinessConstant.EXPLAINS, saasGetHelp.getSelectProductExplains(XbbRefTypeEnum.PURCHASE, businessProductListDTO.getBusinessType(), corpid, PurchaseEnum.PRODUCT.getAttr()));
            }
        }
        // 其他费用
        JSONObject purchaseDataList = purchaseEntityExt.getData();
        Double discount;
        Double otherCharge;
        if (purchaseDataList != null) {
            //discount = purchaseDataList.getDouble(PurchaseEnum.DISCOUNT_RATE.getAttr()) == null ? 0D : purchaseDataList.getDouble(PurchaseEnum.DISCOUNT_RATE.getAttr());
            // 采购单折扣先去掉，后续要加上的再加
            discount = 100D;
            otherCharge = purchaseDataList.getDouble(PurchaseEnum.DISCOUNT_MONEY.getAttr()) == null ? 0D : purchaseDataList.getDouble(PurchaseEnum.DISCOUNT_MONEY.getAttr());
        } else {
            JSONObject productObject = dataList.getJSONObject(PurchaseEnum.PRODUCT.getAttr());
            JSONObject other = productObject == null ? new JSONObject() : productObject.getJSONObject(BusinessConstant.OTHERS);
            if (other == null) {
                other = new JSONObject();
            }
            discount = other.getDouble(StringConstant.PURCHASE_DISCOUNT);
            otherCharge = other.getDouble(StringConstant.PURCHASE_OTHER_CHARGE) == null ? 0D : other.getDouble(StringConstant.PURCHASE_OTHER_CHARGE);
        }
        // 产品共计
        if (discount != null) {
            discount = Arith.round(discount, 2);
        } else {
            discount = 100D;
        }
        JSONObject others = new JSONObject();
        others.put(StringConstant.PURCHASE_DISCOUNT, discount);
        others.put(StringConstant.PURCHASE_OTHER_CHARGE, otherCharge);

        Double totalMoneyWithDiscount = Arith.add(Arith.mul(totalProductMoney, Arith.div(discount, 100D)), otherCharge);

        String totalMoney = attrDecimalPrecisionHelper.formatMoneyPrecision(totalProductMoney, 2);

        others.put(BusinessConstant.TOTAL_PRODUCT_MONEY, totalMoney);
        // 前端不支持1234,3234.23格式
        others.put("totalMoneyWithDiscount", totalMoneyWithDiscount);
        productFinalObj.put(BusinessConstant.OTHERS, others);
        // 产品排序
        productArray.addAll(productSortMap.values());
        productFinalObj.put(StringConstant.PRODUCT_LIST, productArray);
        productFinalObj.put(StringConstant.REDUNDANT_FIELD_ATTR_BEGIN_FLAG, attrStr);
        businessProductListVO.setProduct(productFinalObj);
        businessProductListVO.setPageHelper(pageHelper);
        return businessProductListVO;
    }*/

    /**
     * 获取采购合同产品
     *
     * @param businessProductListDTO 入参
     * @author long.rao
     * @date 2019-08-28 10:24
     **/
    @Override
    public ProductSummaryVO summaryProductList(BusinessProductListDTO businessProductListDTO) throws XbbException {
        // 获取参数
        String corpid = businessProductListDTO.getCorpid();
        Long purchaseId = businessProductListDTO.getDataId();

        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, corpid);
        modelMap.put("purchaseSheetId", purchaseId);
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put("columns", "product_num, product_price,business_num,price_data");
        List<PurchaseProductEntity> purchaseProductEntityList = purchaseProductModel.findEntitys(modelMap);

        PurchaseEntityExt purchaseEntityExt = purchaseModel.getByKey(purchaseId, corpid);
        if (purchaseEntityExt == null) {
            throw new XbbException(PurchaseErrorCodeEnum.API_ERROR_225006);
        }

        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PURCHASE.getCode(), corpid);
        List<FieldAttrEntity> fieldAttrEntities = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        Map<String, FieldAttrEntity> nowFormExplainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //协同团队
        userTeamService.getUserIdMap(Collections.singletonList(purchaseId), corpid, XbbRefTypeEnum.PURCHASE.getCode(), false, mainUserMap, coUserMap);
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(businessProductListDTO, handlerExplainDTO);
        handlerExplainDTO.setCreatorId(purchaseEntityExt.getCreatorId());
        handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(purchaseId, new ArrayList<>()));
        handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(purchaseId, new ArrayList<>()));
        handlerExplainDTO.setExplainList(new ArrayList<>(nowFormExplainMap.values()));
        Boolean invisible = false;
        int accuracy = 0;
        for (FieldAttrEntity fieldAttrEntity : fieldAttrEntities) {
            if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.PRODUCT_TOTAL.getAttr())) {
                invisible = ExplainUtil.isFieldNeedHide(fieldAttrEntity, handlerExplainDTO);
                accuracy = fieldAttrEntity.getAccuracy();
                break;
            }
        }

        Double num = 0D;
        Double count = 0D;
        for (PurchaseProductEntity purchaseProduct : purchaseProductEntityList) {
            Double productNum = purchaseProduct.getProductNum() != null ? purchaseProduct.getProductNum(): 0D;
            Double price = purchaseProduct.getProductPrice() == null ? 0D : purchaseProduct.getProductPrice();
            num = Arith.add(num, purchaseProduct.getBusinessNum() == null ? productNum : purchaseProduct.getBusinessNum());
            if (Objects.nonNull(purchaseProduct.getPriceData()) && !purchaseProduct.getPriceData().isEmpty()) {
                count = Arith.add(count, Arith.mul(purchaseProduct.getBusinessNum(), purchaseProduct.getPriceData().getDouble(PurchaseProductEnum.PURCHASE_PRICE.getAttr())));
            } else {
                count = Arith.add(count, Arith.mul(productNum, price));
            }
        }
        Integer productSize = purchaseProductEntityList.size();
        ProductSummaryVO businessProductListVO = new ProductSummaryVO();
        String summaryInfo = String.format(I18nMessageUtil.getMessage(StringConstant.PRODUCTS_TYPE_NUM), productSize, Arith.doubleToBigDecimal(num));
        businessProductListVO.setSummaryInfo(summaryInfo);
        businessProductListVO.setMoneyInfo(String.format(I18nMessageUtil.getMessage(StringConstant.PRODUCTS_MONEY_COUNT), "", invisible ? StringConstant.INVISIBLE_VALUE : BigDecimal.valueOf(count).setScale(accuracy, BigDecimal.ROUND_HALF_UP).doubleValue()));
        //添加关闭和开启采购合同的按钮
        JSONObject data = purchaseEntityExt.getData();
        String receiveStatus = FastJsonHelper.getStringOrDefaultFromFormData(data, PurchaseEnum.RECEIVE_STATUS.getAttr(), ReceiveStatusEnum.UNRECEIVED.getCode());
        if (!Objects.equals(receiveStatus, ReceiveStatusEnum.RECEIVED.getCode()) && num != 0D) {
            ButtonPojo buttonPojo = new ButtonPojo();
            if (Objects.equals(receiveStatus, ReceiveStatusEnum.CLOSED.getCode()) && businessProductListDTO.getLoginUser().getPermSet().contains(EnableButtonEnum.PURCHASE_ENABLE.getPermission())) {
                buttonPojo.setAttr("purchase");
                buttonPojo.setValue(OperateTypeEnum.ENABLE.getName());
                buttonPojo.setLinkBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
                List<ButtonPojo> topRightButton = new ArrayList<>();
                topRightButton.add(buttonPojo);
                businessProductListVO.setTopRightButton(topRightButton);
            }else if (!Objects.equals(receiveStatus, ReceiveStatusEnum.CLOSED.getCode()) && businessProductListDTO.getLoginUser().getPermSet().contains(EnableButtonEnum.PURCHASE_UNABLE.getPermission())){
                buttonPojo.setAttr("purchase");
                buttonPojo.setValue(OperateTypeEnum.UNABLE.getName());
                buttonPojo.setLinkBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
                List<ButtonPojo> topRightButton = new ArrayList<>();
                topRightButton.add(buttonPojo);
                businessProductListVO.setTopRightButton(topRightButton);
            }
        }
        // 打印那边统一展示
        JSONObject others = new JSONObject();
        others.put("hidePrice", invisible);
        others.put("amount", invisible ? StringConstant.INVISIBLE_VALUE : BigDecimal.valueOf(count).setScale(accuracy, BigDecimal.ROUND_HALF_UP).doubleValue());
        businessProductListVO.setOthers(others);
        return businessProductListVO;
    }


    @Override
    public PurchaseListVO findPurchaseList(PurchaseListDTO purchaseListDTO) throws XbbException {
        PurchaseListVO purchaseListVO = new PurchaseListVO();
        try {
            Map<String, Object> param = BeanUtil.convertBean2Map(purchaseListDTO, true);
            List<PurchaseEntityExt> purchaseList = purchaseModel.findEntitys(param);
            if (Objects.isNull(purchaseList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            purchaseListVO.setPurchaseList(purchaseList);
        } catch (Exception e) {
            LOG.error("purchaseServiceImpl.findPurchaseList 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return purchaseListVO;
    }

    @Override
    public PurchaseUpdateBatchVO updateBatch(PurchaseUpdateBatchDTO purchaseUpdateBatchDTO) throws XbbException {
        PurchaseUpdateBatchVO purchaseUpdateBatchVO = new PurchaseUpdateBatchVO();
        try {
            String corpid = purchaseUpdateBatchDTO.getCorpid();
            List<UpdateDataEntity> updateList = new ArrayList<>();
            purchaseUpdateBatchDTO.getPurchaseList().forEach((item)->{
                updateList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
            });
            purchaseModel.updateBatch(updateList, corpid);
        } catch (Exception e) {
            LOG.error("purchaseServiceImpl.updateBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return purchaseUpdateBatchVO;
    }
    /**
     * 禁止调用
     *
     * @param purchaseUpdateBatchDTO
     * @param isUpdateTime
     * @param needThrow
     * @return
     * @throws XbbException
     */
    @Override
    public PurchaseUpdateBatchVO updateBatch(PurchaseUpdateBatchDTO purchaseUpdateBatchDTO, Boolean isUpdateTime, boolean needThrow) throws XbbException {
        PurchaseUpdateBatchVO purchaseUpdateBatchVO = new PurchaseUpdateBatchVO();
        try {
            String corpid = purchaseUpdateBatchDTO.getCorpid();
            List<UpdateDataEntity> updateList = new ArrayList<>();
            List<PurchaseUpdateDTO> purchaseList = purchaseUpdateBatchDTO.getPurchaseList();
            if (Objects.nonNull(purchaseList) && !purchaseList.isEmpty()) {
                purchaseList.forEach((item)->{
                    if ( isUpdateTime ) {
                        updateList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid));
                    } else {
                        updateList.add(ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid, item.getUpdateTime()));
                    }
                });
            }
            if (!updateList.isEmpty()) {
                purchaseModel.updateBatch(updateList, corpid, needThrow);
            }
        } catch (Exception e) {
            LOG.error("purchaseServiceImpl.updateBatch (包含跟新时间)执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return purchaseUpdateBatchVO;
    }

    @Override
    public PurchaseDeleteBatchVO deleteBatch(PurchaseDeleteBatchDTO purchaseDeleteBatchDTO) throws XbbException {
        PurchaseDeleteBatchVO purchaseDeleteBatchVO = new PurchaseDeleteBatchVO();
        try {
            List<String> errorDataList = new ArrayList<>();
            Set<String> errorDataSet = new HashSet<>();
            Set<String> errorTypeSet = new HashSet<>();
            List<String> errorTypeList = new ArrayList<>();
            // 删除采购合同后同步，关联产品，负责人
            List<Long> idIn = purchaseDeleteBatchDTO.getDataIdList();
            if ( idIn.size() > BasicConstant.MAX_DEL_BATCH_COUNT ) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100079.getCode(), SystemErrorCodeEnum.API_ERROR_100079.getMsg(), BasicConstant.MAX_DEL_BATCH_COUNT);
            }
            Map<String, Object> param = BeanUtil.convertBean2Map(purchaseDeleteBatchDTO, true);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("idIn", idIn);
            List<PurchaseEntityExt> purchaseList = purchaseModel.findEntitys(param);
            if(Objects.isNull(purchaseList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            String corpid = purchaseDeleteBatchDTO.getCorpid();
            // 采购合同删除校验
            List<String> field = new ArrayList<>();
            List<PaasFormDataEntityExt> entityExts;
            // 查询采购合同是否关联采购入库单
            List<Long> linkPurchaseInstockId = new ArrayList<>();
            List<String> purchaseSerialNos = new ArrayList<>();
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termsQuery("data." + PurchaseInstockEnum.REF_ID.getAttr(), idIn));
            boolQueryBuilder.filter(termQuery("data." + InstockEnum.TYPE.getAttr(), InstockTypeEnum.PURCHASE_INSTOCK.getCode()));
            boolQueryBuilder.filter(termsQuery("flowStatus", FlowStatusEnum.getStatisticType()));
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            // 设置join_field
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PURCHASE_INSTOCK.getType()));
            searchSourceBuilder.query(boolQueryBuilder);
            field.add(PurchaseInstockEnum.REF_ID.getAttr());
            // 查询es 获取关联采购入库单
            entityExts = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_PURCHASE_INSTOCK, field, null, null);
            if (Objects.nonNull(entityExts) && entityExts.size() > 0) {
                for (PaasFormDataEntityExt entity : entityExts) {
                    JSONObject data = entity.getData();
                    Long purchaseContractId = data.getLong(PurchaseInstockEnum.REF_ID.getAttr());
                    linkPurchaseInstockId.add(purchaseContractId);
                }
                for (PurchaseEntityExt purchaseEntityExt : purchaseList) {
                    if (linkPurchaseInstockId.contains(purchaseEntityExt.getId())) {
                        purchaseSerialNos.add(purchaseEntityExt.getSerialNo());
                    }
                }
                throw new XbbException(PurchaseErrorCodeEnum.API_ERROR_225031, PurchaseErrorCodeEnum.API_ERROR_225031.getMsg(), purchaseSerialNos.toString());
            }

            // 查询采购合同是否关联采购退货单
            BoolQueryBuilder queryBuilder = boolQuery();
            List<Long> linkReturnPurchaseId = new ArrayList<>();
            queryBuilder.filter(termQuery("corpid.keyword", corpid));
            queryBuilder.filter(termsQuery("data." + ReturnedPurchaseEnum.PURCHASE_SHEET_ID.getAttr(), idIn));
            queryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            // 设置join_field
            queryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_RETURNED_PURCHASE.getType()));
            searchSourceBuilder.query(queryBuilder);
            field.clear();
            field.add(ReturnedPurchaseEnum.PURCHASE_SHEET_ID.getAttr());
            entityExts = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_RETURNED_PURCHASE, field, null, null);
            if (Objects.nonNull(entityExts) && entityExts.size() > 0) {
                for (PaasFormDataEntityExt entity : entityExts) {
                    JSONObject data = entity.getData();
                    Long purchaseContractId = data.getLong(ReturnedPurchaseEnum.PURCHASE_SHEET_ID.getAttr());
                    linkReturnPurchaseId.add(purchaseContractId);
                }
                for (PurchaseEntityExt purchaseEntityExt : purchaseList) {
                    if (linkReturnPurchaseId.contains(purchaseEntityExt.getId())) {
                        purchaseSerialNos.add(purchaseEntityExt.getSerialNo());
                    }
                }
                throw new XbbException(PurchaseErrorCodeEnum.API_ERROR_225030, PurchaseErrorCodeEnum.API_ERROR_225030.getMsg(), purchaseSerialNos.toString());
            }

            List<Long> payPlanSheetInApprove = new ArrayList<>();
            if (commonHelp.isOpenWorkFlow(corpid)) {
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(PaySheetEnum.getEsAttr4Keyword(PaySheetEnum.LINK_PURCHASE), idIn));
                boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET.getType()));
                List<PaasFormDataEntityExt> paySheetFormDataList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAYPLAN_SHEET,
                        boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(PaySheetEnum.getAttrConnectData(PaySheetEnum.LINK_PURCHASE), FieldTypeEnum.DATAID.getAlias()));
                paySheetFormDataList.forEach(item -> {
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data)) {
                        JSONArray purchaseIds = data.getJSONArray(PaySheetEnum.LINK_PURCHASE.getAttr());
                        for (Object obj : purchaseIds) {
                            if (Objects.nonNull(obj)) {
                                Long purchaseId = StringUtil.StringToLong(obj.toString());
                                if (Objects.nonNull(purchaseId)) {
                                    payPlanSheetInApprove.add(purchaseId);
                                }
                            }
                        }
                    }
                });
            } else {
                // 获取付款单是否在审批中
                List<PaasProcessDataEntity> payPlanSheetProcessList = paasProcessDataModel.getInApprovalDataByIdCondition(XbbRefTypeEnum.PAY_SHEET.getCode(), PaySheetEnum.LINK_PURCHASE.getAttr(), idIn, corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
                if (Objects.isNull(payPlanSheetProcessList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                payPlanSheetProcessList.forEach(item -> {
                    JSONObject data = JSON.parseObject(item.getData());
                    if (Objects.nonNull(data)) {
                        JSONArray purchaseIds = data.getJSONArray(PaySheetEnum.LINK_PURCHASE.getAttr());
                        for (Object obj : purchaseIds) {
                            if (Objects.nonNull(obj)) {
                                Long purchaseId = StringUtil.StringToLong(obj.toString());
                                if (Objects.nonNull(purchaseId)) {
                                    payPlanSheetInApprove.add(purchaseId);
                                }
                            }
                        }
                    }
                });
            }

            List<Object> linkIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            idIn.forEach(id->{
                linkIdIn.add(id);
            });
            Map<Long, PaasFormDataEntityExt> paySheetEntityExtMap = fundHelp.getEsDataMapByLinkIds(XbbRefTypeEnum.PAY_SHEET,corpid, linkIdIn, PaySheetEnum.LINK_PURCHASE.getAttr());
            for (PurchaseEntityExt item:purchaseList) {
                Long purchaseId = item.getId();
                PaasFormDataEntityExt paymentSheetEntityExt = paySheetEntityExtMap.get(purchaseId);
                if ( Objects.nonNull(paymentSheetEntityExt) ){
                    payPlanSheetInApprove.add(purchaseId);
                }
            }
            List<Long> linkRefundId = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (Long purchaseId : idIn) {
                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put(ParameterConstant.CORPID, corpid);
                params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                List<PaasFormDataEntityExt> paasFormDataEntityExts = paasEsModel.selectByOneCondition(RedundantTemplateTypeEnum.RETURNED_PURCHASE.getCode(),
                        ReturnedPurchaseEnum.PURCHASE_SHEET_ID.getAttr(), purchaseId, params, IndexTypeEnum.IDX_SAAS_RETURNED_PURCHASE);
                if(!paasFormDataEntityExts.isEmpty()){
                    // 包装所有已经关联退货退款的合同id
                    linkRefundId.add(purchaseId);
                }
            }

            List<Long> purchaseInvoiceInApprove = new ArrayList<>();
            if (commonHelp.isOpenWorkFlow(corpid)) {
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(PurchaseInvoiceEnum.getEsAttr4Keyword(PurchaseInvoiceEnum.PURCHASE_ID), idIn));
                boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PURCHASE_INVOICE.getType()));
                List<PaasFormDataEntityExt> purchaseInvoiceFormDataList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PURCHASE_INVOICE,
                        boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(PurchaseInvoiceEnum.getAttrConnectData(PurchaseInvoiceEnum.PURCHASE_ID), FieldTypeEnum.DATAID.getAlias()));
                purchaseInvoiceFormDataList.forEach(item -> {
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data)) {
                        JSONArray purchaseIds = data.getJSONArray(PurchaseInvoiceEnum.PURCHASE_ID.getAttr());
                        for (Object obj : purchaseIds) {
                            Long purchaseId = StringUtil.StringToLong((String) obj);
                            if (Objects.nonNull(purchaseId)) {
                                purchaseInvoiceInApprove.add(purchaseId);
                            }
                        }
                    }
                });
            } else {
                // 获取销项发票是否在审批中
                List<PaasProcessDataEntity> invoiceProcessList = paasProcessDataModel.getInvoiceInApprovalDataByIdConditionJsonArray(XbbRefTypeEnum.PURCHASE_INVOICE.getCode(), PurchaseInvoiceEnum.PURCHASE_ID.getAttr(), idIn, corpid, Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
                invoiceProcessList.forEach(item -> {
                    JSONObject data = JSON.parseObject(item.getData());
                    if (Objects.nonNull(data)) {
                        JSONArray purchaseIds = data.getJSONArray(PurchaseInvoiceEnum.PURCHASE_ID.getAttr());
                        for (Object obj : purchaseIds) {
                            Long purchaseId = StringUtil.StringToLong((String) obj);
                            if (Objects.nonNull(purchaseId)) {
                                purchaseInvoiceInApprove.add(purchaseId);
                            }
                        }
                    }
                });
            }
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("purchaseIdIn",idIn);
            map.put("corpid",corpid);
            map.put("del",DelEnum.NORMAL);
            List<PurchaseInvoiceRelationshipEntity> purchaseInvoiceRelationshipEntityList = purchaseInvoiceRelationshipModel.findEntitys(map);
            Set<Long> invoiceRelationshipPurchaseList = new HashSet<>();
            Map<Long,Long> purchaseRefInvoiceId = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            purchaseInvoiceRelationshipEntityList.forEach(purchaseInvoiceRelationshipEntity -> {
                invoiceRelationshipPurchaseList.add(purchaseInvoiceRelationshipEntity.getPurchaseId());
                purchaseRefInvoiceId.put(purchaseInvoiceRelationshipEntity.getPurchaseId(),purchaseInvoiceRelationshipEntity.getPurchaseInvoiceId());
            });
            //查询产品名称
            Map<String, String> purchaseNoAndName= new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for(PaasFormDataEntityExt purchase : purchaseList){
                JSONObject data = purchase.getData();
                String productNo = purchase.getSerialNo();
                String name = FastJsonHelper.getStringOrDefaultFromFormData(data, PurchaseEnum.PURCHASE_NAME.getAttr(), "");
                purchaseNoAndName.put(productNo, name);
                if(linkRefundId.contains(purchase.getId())){
                    idIn.remove(purchase.getId());
                    errorTypeSet.add(I18nMessageUtil.getMessage(ErrorMessageConstant.HAVE_PURCHASE_REFUND_NOT_DEL));
                    errorDataSet.add(productNo);
                }
                if(payPlanSheetInApprove.contains(purchase.getId())) {
                    idIn.remove(purchase.getId());
                    errorTypeSet.add(I18nMessageUtil.getMessage(ErrorMessageConstant.HAVE_PAY_PLAN_SHEET_NOT_DEL));
                    errorDataSet.add(productNo);
                }

                if(purchaseInvoiceInApprove.contains(purchase.getId())){
                    idIn.remove(purchase.getId());
                    errorTypeSet.add(I18nMessageUtil.getMessage(ErrorMessageConstant.HAVE_PURCHASE_INVOICE_APPROVE_NOT_DEL));
                    errorDataSet.add(productNo);
                }
                if(invoiceRelationshipPurchaseList.contains(purchase.getId())){
                    idIn.remove(purchase.getId());
                    errorTypeSet.add(I18nMessageUtil.getMessage(ErrorMessageConstant.HAVE_PURCHASE_INVOICE_NOT_DEL));
                    errorDataSet.add(productNo);
                }

            }
            errorDataList.addAll(errorDataSet);
            errorTypeList.addAll(errorTypeSet);
            if(!idIn.isEmpty()) {
                purchaseDeleteBatchVO.setDeleteIds(idIn);
                if(BasicConstant.ONE.equals(purchaseDeleteBatchDTO.getSingleFlag())
                        && BasicConstant.ONE.equals(idIn.size())){
                    purchaseModel.deleteByKey(idIn.get(0),corpid);
                }else {
                    purchaseModel.deleteBatch(idIn, corpid);
                }
                PushNotifyDeleteDTO pushNotifyDeleteDTO = new PushNotifyDeleteDTO();
                BeanUtil.copyProperties(purchaseDeleteBatchDTO, pushNotifyDeleteDTO);
                pushNotifyDeleteDTO.setNeedDelNotifyIdList(idIn);
                pushNotifyDeleteDTO.setBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
                pushNotifyService.deletePushNotify(pushNotifyDeleteDTO);

                // 删除付款计划
                PayPlanDeleteBatchDTO payPlanDeleteBatchDTO = new PayPlanDeleteBatchDTO();
                BeanUtil.copyProperties(purchaseDeleteBatchDTO, payPlanDeleteBatchDTO);
                payPlanDeleteBatchDTO.setDataIdList(idIn);
                payPlanService.deleteBatchByPurchaseId(payPlanDeleteBatchDTO);

                // 删除采购合同产品
                PurchaseProductDeleteBatchDTO purchaseProductDeleteBatchDTO = new PurchaseProductDeleteBatchDTO();
                BeanUtil.copyProperties(purchaseDeleteBatchDTO, purchaseProductDeleteBatchDTO);
                purchaseProductDeleteBatchDTO.setPurchaseIdIn(idIn);
                // 删除采购合同 更新采购结存表及智能补货数据表
                Map<String, Object> purchaseProductParam = new HashMap<>(16);
                purchaseProductParam.put("corpid", corpid);
                purchaseProductParam.put("purchaseSheetIdIn", idIn);
                purchaseProductParam.put("del", 0);
                purchaseProductParam.put(ParameterConstant.ORDER_BY_STR, StringConstant.SAAS_LINK_BUSINESS_ID);
                // 获取所有采购产品数据
                List<PurchaseProductEntity> purchaseProductEntityList = purchaseProductModel.findEntitys(purchaseProductParam);
                // 因为下面需要用到del为0的数据 所以更新del放在最后面
                purchaseProductService.deleteByPurchaseIdIn(purchaseProductDeleteBatchDTO);
                waitPurchaseService.deletePurchase(corpid,purchaseProductEntityList);

                // TODO 删除关联审批记录
                // 删除采购合同后合同重置采购合同Id
                if(!purchaseList.isEmpty()) {
                    List<Long> contractId = new ArrayList<>();
                    purchaseList.forEach((item)->{
                        JSONObject data = item.getData();
                        if (Objects.nonNull(data) && Objects.nonNull(data.get(PurchaseEnum.REF_ID.getAttr()))) {
                            contractId.add(data.getLong(PurchaseEnum.REF_ID.getAttr()));
                        }
                    });
                    if (!contractId.isEmpty()) {
                        ContractUpdateBatchDTO contractUpdateBatchDTO = new ContractUpdateBatchDTO();
                        BeanUtil.copyProperties(purchaseDeleteBatchDTO, contractUpdateBatchDTO, true);
                        List<ContractUpdateDTO> contractUpdateList = new ArrayList<>();
                        contractId.forEach((item)->{
                            ContractUpdateDTO contractUpdateDTO = new ContractUpdateDTO();
                            contractUpdateDTO.setId(item);
                            JSONObject data = new JSONObject();
                            data.put(ContractEnum.PURCHASE_ID.getAttr(), 0);
                            contractUpdateDTO.setData(data);
                            contractUpdateList.add(contractUpdateDTO);
                        });
                        if(!contractUpdateList.isEmpty()) {
                            contractUpdateBatchDTO.setContractUpdateList(contractUpdateList);
                            contractService.updateBatch(contractUpdateBatchDTO);
                        }
                    }
                }
            }
            purchaseDeleteBatchVO.setErrorDataList(errorDataList);
            purchaseDeleteBatchVO.setErrorTypeList(errorTypeList);
            purchaseDeleteBatchVO.setErrorDataMemo(SaasDeleteHelp.getErrorDataMemo(errorTypeList, errorDataList));
            //生成删除日志(区分单个删除和批量删除)
            String userId = purchaseDeleteBatchDTO.getUserId();
            String userName = purchaseDeleteBatchDTO.getLoginUserName();
            List<String> list = new ArrayList<>();
            Iterator<String> iterator = purchaseNoAndName.keySet().iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                String value = purchaseNoAndName.get(key);
                if(StringUtil.isEmpty(value)){
                    list.add(key);
                } else {
                    StringBuilder sb = new StringBuilder();
                    sb.append(key).append("（").append(value).append("）");
                    list.add(sb.toString());
                }
            }
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
            if (Objects.equals(1, purchaseDeleteBatchDTO.getIsBusinessRule())) {
                operateTypeEnum = OperateTypeEnum.RULE_DELETE;
            }
            String nameStr = StringUtils.join(list, "，");
            if(idIn.size() > 1){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, XbbRefTypeEnum.PURCHASE.getName(), idIn.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(PurchaseEnum.SHEET_NO.getAttrName());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.PURCHASE, operateTypeEnum,
                        "", "", memo, purchaseDeleteBatchDTO.getHttpHeader());
            } else if (Objects.equals(idIn.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, XbbRefTypeEnum.PURCHASE.getName(), nameStr);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PURCHASE, operateTypeEnum,
                        idIn.get(0).toString(), nameStr, memo, purchaseDeleteBatchDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("purchaseServiceImpl.deleteBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return purchaseDeleteBatchVO;
    }

    @Override
    public void batchEditAttr(PurchaseEditAttrUpdateDTO purchaseEditAttrUpdateDTO) throws XbbException {
        try {
            List<PurchaseUpdateDTO> purchaseList = new ArrayList<>();
            purchaseEditAttrUpdateDTO.getDataIdList().forEach((item)->{
                PurchaseUpdateDTO purchaseUpdateDTO = new PurchaseUpdateDTO();
                purchaseUpdateDTO.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(purchaseEditAttrUpdateDTO.getFieldEditedList());
                purchaseUpdateDTO.setData(data);
                purchaseList.add(purchaseUpdateDTO);
            });
            List<PurchaseEntityExt> purchaseEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (!purchaseList.isEmpty()) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid", purchaseEditAttrUpdateDTO.getCorpid());
                param.put("idIn", purchaseEditAttrUpdateDTO.getDataIdList());
                purchaseEntityList = purchaseModel.findEntitys(param);
                if (Objects.isNull(purchaseEntityList)){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                //权限团队校验前置了
                List<Long> errorIdList = new ArrayList<>();
//                List<Long> errorIdList = userTeamHelp.batchTeamMembersCheckEditPermission(purchaseEditAttrUpdateDTO.getBusinessType(), purchaseEditAttrUpdateDTO.getSaasMark(),
//                        purchaseEditAttrUpdateDTO.getMenuId(), purchaseEditAttrUpdateDTO.getLoginUser(), purchaseEditAttrUpdateDTO.getDistributorMark(),
//                        purchaseEditAttrUpdateDTO.getDataIdList(), new HashMap<>());
                List<String> errorNameList = new ArrayList<>();
                for (PurchaseEntityExt purchaseEntityExt : purchaseEntityList) {
                    if (errorIdList.contains(purchaseEntityExt.getId())) {
                        errorNameList.add(purchaseEntityExt.getData().getString(PurchaseEnum.PURCHASE_NAME.getAttr()));
                    }
                }
                String nameStr = StringUtils.join(errorNameList, "、");
                if (CollectionUtils.isNotEmpty(errorNameList)) {
                    throw new XbbException(UserTeamErrorCodeEnum.API_ERROR_271038.getCode(), String.format(UserTeamErrorCodeEnum.API_ERROR_271038.getMsg(), nameStr));
                }
                PurchaseUpdateBatchDTO purchaseUpdateBatchDTO = new PurchaseUpdateBatchDTO();
                BeanUtil.copyProperties(purchaseEditAttrUpdateDTO, purchaseUpdateBatchDTO);
                purchaseUpdateBatchDTO.setPurchaseList(purchaseList);
                updateBatch(purchaseUpdateBatchDTO);
            }

            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PurchaseEntityExt item : purchaseEntityList) {
                dataIdList.add(item.getId());
                JSONObject data = item.getData();
                String serialNo = item.getSerialNo();
                String opObjectName = data.getString(PurchaseEnum.PURCHASE_NAME.getAttr());
                StringBuilder sb = new StringBuilder();
                opObjectName = opObjectName == null ? serialNo : sb.append(serialNo).append("（").append(opObjectName).append("）").toString();
                updataItemList.add(opObjectName);
            }
            String updataItem = StringUtils.join(updataItemList, "，");
            String userId = purchaseEditAttrUpdateDTO.getUserId();
            String corpid = purchaseEditAttrUpdateDTO.getCorpid();
            String loginUserName = purchaseEditAttrUpdateDTO.getLoginUserName();
            // 标签特殊处理
            Integer fieldType = purchaseEditAttrUpdateDTO.getFieldType();
            Boolean isFieldDependence = purchaseEditAttrUpdateDTO.getIsFieldDependence();
            logHelp.analysisLabel(corpid, fieldType, isFieldDependence,purchaseEditAttrUpdateDTO.getLogFieldEditedList());

            String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(purchaseEditAttrUpdateDTO.getLogFieldEditedList());
            if(dataIdList.size() > 1 ){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.PURCHASE.getName(),
                        changedLogItemsStr, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.PURCHASE.getName());
                infoArrPojo.setContent(updataItem);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.PURCHASE, OperateTypeEnum.EDIT,
                        "", "", memo, purchaseEditAttrUpdateDTO.getHttpHeader());
            } else if (Objects.equals(dataIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.PURCHASE.getName(), updataItem,
                        changedLogItemsStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.PURCHASE, OperateTypeEnum.EDIT,
                        dataIdList.get(0).toString(), updataItem, memo, purchaseEditAttrUpdateDTO.getHttpHeader());
            }
        } catch (XbbException e){
            throw e;
        } catch (Exception e) {
            LOG.error("bomBillService.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }




    /**
     * 保存前要处理的关联产品和采购合同入库信息
     *
     * @param purchaseEntityExt 采购合同参数
     * @param isNew 是否新建
     * @throws XbbException 异常
     * @date 2019/2/27 14:53
     * @author Jian.Wang
     */
    @Override
    public void dealWithPurchaseProduct(PurchaseEntityExt purchaseEntityExt, boolean isNew,Integer taskType) throws XbbException {
        // 采购合同关联产品特殊处理
        JSONObject purchaseProductList = purchaseEntityExt.getData();

        Long purchaseId = purchaseEntityExt.getId();
        String corpid = purchaseEntityExt.getCorpid();
        // 更新采购合同关联产品
        setPurchaseProduct(purchaseProductList,isNew,corpid,purchaseId,taskType);
        // 编辑情况下，更新采购合同入库状态
        //setPurchaseAllInComing(purchaseEntityExt, isNew);
    }

    /**
     * 更新采购合同关联产品
     * @param data 参数集合
     * @param isNew 是否是新建
     * @param corpid 公司Id
     * @param purchaseId 采购合同ID
     * @date 2019/2/27 20:17
     * @author Jian.Wang
     * @throws XbbException 异常
     */
    private void setPurchaseProduct(JSONObject data, boolean isNew, String corpid, Long purchaseId,Integer taskType) throws XbbException {
        Map<Long, PurchaseProductEntity> originProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 智能补货编辑前后的总量Map
        Map<Long,Double> changeBeforeNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,Double> changeAfterNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 以销定购编辑前后的总量map
        Map<String ,Double> balanceBeforeNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String ,Double> balanceAfterNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> onlyKeyList = new ArrayList<>();
        // 本次采购合同动到的所有产品ID
        List<Long> allProductIdList = new ArrayList<>();
        Map<Long, PurchaseProductEntity> withdrawFailedProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,Double> instockNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,Double> outstockNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Boolean isOldData = false;
        if (!isNew) {
            //非新建情况下，取得采购合同编辑前的关联产品
            List<PurchaseProductEntity> purchaseProductList = purchaseProductModel.getProductsByPurchaseId(corpid,purchaseId, Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.APPROVE_FAILED.getDel()));
            isOldData = judgePurchaseisOld(purchaseId, corpid);
            for (PurchaseProductEntity purchaseProduct : purchaseProductList) {
                Long productId = purchaseProduct.getProductId();
                originProductMap.put(purchaseProduct.getId(), purchaseProduct);
                if (Objects.equals(DelEnum.NORMAL.getDel(), purchaseProduct.getDel())) {
                    allProductIdList.add(productId);
                }
                // 记录智能补货数量
                if(changeBeforeNumMap.containsKey(purchaseProduct.getProductId())){
                    changeBeforeNumMap.put(productId,Arith.add(changeBeforeNumMap.get(productId),purchaseProduct.getProductNum()));
                }else {
                    changeBeforeNumMap.put(productId,purchaseProduct.getProductNum());
                }
                // 记录采购结存数量
                if (Objects.nonNull(purchaseProduct.getContractId()) && Objects.nonNull(purchaseProduct.getContractProductId())){
                    String onlyKey = purchaseProduct.getContractProductId() + "_" + purchaseProduct.getProductId();
                    if (balanceBeforeNumMap.containsKey(onlyKey)){
                        balanceBeforeNumMap.put(onlyKey,Arith.add(balanceBeforeNumMap.get(onlyKey),purchaseProduct.getProductNum()));
                    }else {
                        balanceBeforeNumMap.put(onlyKey,purchaseProduct.getProductNum());
                    }
                }
                //将所有回退的产品信息保存下来
                if (Objects.equals(DelEnum.APPROVE_FAILED.getDel(), purchaseProduct.getDel())){
                    withdrawFailedProductMap.put(purchaseProduct.getId(), purchaseProduct);
                }
                Double instockNum = instockNumMap.getOrDefault(purchaseProduct.getProductId(),0D);
                instockNumMap.put(purchaseProduct.getProductId(),Arith.add(instockNum,purchaseProduct.getInstockNum()));
                Double outstockNum = outstockNumMap.getOrDefault(purchaseProduct.getProductId(),0D);
                outstockNumMap.put(purchaseProduct.getProductId(),Arith.add(outstockNum,purchaseProduct.getOutstockNum()));
            }
        }
        //新增产品
        List<PurchaseProductEntity> productAddList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //编辑产品
        List<PurchaseProductEntity> productUpdateList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 采购产品数据
        JSONArray productListArray = data.getJSONArray(PurchaseEnum.PRODUCT.getAttr());
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,productListArray);
        Integer sort = 0;

        for (int i = 0; i < productListArray.size(); i++) {
            JSONObject jsonObject = productListArray.getJSONObject(i);
            Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            allProductIdList.add(pageProductId);
            Long businessProductId = jsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID);
            Double productNum = jsonObject.getDouble(PurchaseProductEnum.NUM.getAttr());
            Double price = jsonObject.getDouble(PurchaseProductEnum.PURCHASE_PRICE.getAttr());
            price = price != null ? price : 0;
            if (changeAfterNumMap.containsKey(pageProductId)){
                changeAfterNumMap.put(pageProductId,Arith.add(changeAfterNumMap.get(pageProductId),productNum));
            }else {
                changeAfterNumMap.put(pageProductId,productNum);
            }
            String memo = jsonObject.getString(PurchaseProductEnum.MEMO.getAttr());

            // TODO 设置精度
            Double money = productNum * price;
            if (Objects.equals(jsonObject.getDouble(PurchaseProductEnum.SUBTOTAL.getAttr()), 0D) || Objects.isNull(jsonObject.get(PurchaseProductEnum.SUBTOTAL.getAttr()))) {
                jsonObject.put(PurchaseProductEnum.SUBTOTAL.getAttr(), money);
            }
            boolean addProductFlag = formDataValidateProductHelp.addProductFlag(businessProductId);
            PurchaseProductEntity purchaseProduct;
            if (addProductFlag) {
                //新增产品
                purchaseProduct = new PurchaseProductEntity();
                purchaseProduct.setInstockNum(0D);
                productAddList.add(purchaseProduct);
            } else if (originProductMap.containsKey(businessProductId)) {
                //编辑产品
                purchaseProduct = originProductMap.get(businessProductId);
                if (Objects.equals(DelEnum.APPROVE_FAILED.getDel(), purchaseProduct.getDel())) {
                    purchaseProduct.setDel(DelEnum.NORMAL.getDel());
                }
                productUpdateList.add(purchaseProduct);
                //只剩删除的产品
                originProductMap.remove(businessProductId);
            } else {
                //删除产品
                continue;
            }
            //将回退后重新提交的产品过滤
            if (withdrawFailedProductMap.containsKey(businessProductId)){
                withdrawFailedProductMap.remove(businessProductId);
            }
            JSONObject productData = productMap.get(pageProductId).getData();
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.equals(enableMultiUnit, 1)) {
                formDataValidateProductHelp.setBusinessUnit(jsonObject, purchaseProduct);
                purchaseProduct.setProductUnit(jsonObject.getString(SelectProductEnum.UNIT.getAttr()));
            } else {
                purchaseProduct.setProductUnit(productData.getString(ProductEnum.UNIT.getAttr()));
                jsonObject.put(PurchaseProductEnum.UNIT.getAttr(),productData.getString(ProductEnum.UNIT.getAttr()));
            }
            purchaseProduct.setCorpid(corpid);
            purchaseProduct.setPurchaseSheetId(purchaseId == null ? 0L : purchaseId);
            purchaseProduct.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            purchaseProduct.setProductId(pageProductId);
            purchaseProduct.setProductNum(productNum);
            purchaseProduct.setProductPrice(price);
            purchaseProduct.setMoney(money);
            purchaseProduct.setMemo(memo);
            purchaseProduct.setDiscount(100D);
            purchaseProduct.setDel(0);
            purchaseProduct.setSort(sort);
            purchaseProduct.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
            String productNo = productData.getString(ProductEnum.PRODUCT_NO.getAttr());
            productNo = Objects.isNull(productNo) ? "" : productNo;
            purchaseProduct.setProductNo(productNo);
            purchaseProduct.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            String unit = productData.getString(ProductEnum.UNIT.getAttr());
            unit = Objects.isNull(unit) ? "" : unit;

            purchaseProduct.setThumbnail(productData.getString(ProductEnum.THUMBNAIL.getAttr()));
            purchaseProduct.setOtherCharge(0D);
            purchaseProduct.setData(jsonObject);
//            setProductParam(purchaseProduct);
            //老数据维护一下入库数
            if (!isNew && isOldData){
                if (instockNumMap.containsKey(purchaseProduct.getProductId())){
                    Double amendNum = instockNumMap.get(purchaseProduct.getProductId());
                    Double amendOutNum = outstockNumMap.getOrDefault(purchaseProduct.getProductId(), 0D);
                    Double instockNum = purchaseProduct.getProductNum() < amendNum ? purchaseProduct.getProductNum() : amendNum;
                    purchaseProduct.setInstockNum(instockNum);
                    amendNum = Arith.sub(amendNum,instockNum);
                    Double outstockNum = purchaseProduct.getProductNum() < amendOutNum ? purchaseProduct.getProductNum() : amendOutNum;
                    purchaseProduct.setOutstockNum(outstockNum);
                    amendOutNum = Arith.sub(amendOutNum,outstockNum);
                    if (amendNum > 0){
                        instockNumMap.put(purchaseProduct.getProductId(),amendNum);
                    }else {
                        instockNumMap.remove(purchaseProduct.getProductId());
                    }
                    if (amendOutNum > 0){
                        outstockNumMap.put(purchaseProduct.getProductId(),amendOutNum);
                    }else {
                        outstockNumMap.remove(purchaseProduct.getProductId());
                    }
                }else {
                    purchaseProduct.setInstockNum(0D);
                    purchaseProduct.setOutstockNum(0D);
                }
            }
            // 新建采购合同 将合同与产品关联起来
            String contractNo = jsonObject.getString(PurchaseProductEnum.CONTRACT_NO.getAttr());
            Object cid = jsonObject.get("contractId");
            Object cpid = jsonObject.get("contractProductId");
            if (Objects.nonNull(contractNo) && Objects.nonNull(cid) && Objects.nonNull(cpid)){
                Long contractId = Long.valueOf(cid.toString());
                purchaseProduct.setContractId(contractId);
                Long contractProductId = Long.valueOf(cpid.toString());
                purchaseProduct.setContractProductId(contractProductId);
                String onlykey = contractProductId + "_" + pageProductId;
                if (balanceAfterNumMap.containsKey(onlykey)){
                    balanceAfterNumMap.put(onlykey,Arith.add(balanceAfterNumMap.get(onlykey),productNum));
                }else {
                    balanceAfterNumMap.put(onlykey,productNum);
                    onlyKeyList.add(onlykey);
                }
            }
            sort++;
        }

        purchaseProductModel.insertBatch(productAddList);

        purchaseProductModel.updateMulti(productUpdateList, corpid);
        List<Long> deleteList = new ArrayList<>();
        List<PurchaseProductEntity> delList = new ArrayList<>();
        for (Map.Entry<Long, PurchaseProductEntity> entry : originProductMap.entrySet()) {
            PurchaseProductEntity delProduct = entry.getValue();
            deleteList.add(delProduct.getId());
            delList.add(delProduct);
        }
        //删除剩下的回退产品
        for (Map.Entry<Long, PurchaseProductEntity> entry : withdrawFailedProductMap.entrySet()) {
            PurchaseProductEntity delProduct = entry.getValue();
            deleteList.add(delProduct.getId());
        }
        purchaseProductModel.deleteBatch(deleteList, corpid, DelEnum.DELETE.getDel());
        boolean isAgainCommit = Objects.equals(TaskTypeEnum.AGAIN_COMMIT.getType(),taskType);
        // 智能补货产品变更数量
        Map<Long,Double> smartNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionUtils.isNotEmpty(allProductIdList)){
            for (Long productId : allProductIdList) {
                // 重新提交不计算差值
                Double beforeNum = 0D;
                if (!isAgainCommit){
                    beforeNum = changeBeforeNumMap.getOrDefault(productId, 0D);
                }
                Double afterNum = changeAfterNumMap.getOrDefault(productId, 0D);
                smartNumMap.put(productId,Arith.sub(afterNum,beforeNum));
            }
        }
        // 以销定购产品变更数量
        Map<String,Double> waitPurchaseNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionUtils.isNotEmpty(onlyKeyList)){
            for (String onlyKey : onlyKeyList) {
                // 重新提交不计算差值
                Double balanceBeforeNum = 0D;
                if (!isAgainCommit){
                    balanceBeforeNum = balanceBeforeNumMap.getOrDefault(onlyKey, 0D);
                }
                Double balanceAfterNum = balanceAfterNumMap.getOrDefault(onlyKey, 0D);
                waitPurchaseNumMap.put(onlyKey,Arith.sub(balanceAfterNum,balanceBeforeNum));
            }
        }
        // 处理采购结存及智能补货数据
        waitPurchaseService.formatPurchase(corpid,productAddList,productUpdateList,delList,smartNumMap,waitPurchaseNumMap,isAgainCommit);

    }

    /**
     * 判断是否是老数据
     * @param purchaseId
     * @param corpid
     * @return
     */
    private Boolean judgePurchaseisOld(Long purchaseId, String corpid) throws XbbException {
        Boolean isOld = false;
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE), InstockTypeEnum.PURCHASE_INSTOCK.getCode()));
        boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID), purchaseId));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_INSTOCK.getType()));
        sourceBuilder.query(boolQueryBuilder);
        sourceBuilder.sort(new FieldSortBuilder("addTime").order(SortOrder.DESC));
        //分页
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, 1);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_INSTOCK.getIndex());
        searchRequest.source(sourceBuilder);
        XbbAggregatedPage<PaasFormDataEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest,searchRequest, PaasFormDataEntityExt.class);
        if (esEntities.getTotalElements() >= 1) {
            List<PaasFormDataEntityExt> content = esEntities.getContent();
            Long dataId = content.get(0).getDataId();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("intoWarehouseId", dataId);
            param.put("pageSize", 1);
            List<InstockProductEntity> entitys = instockProductModel.findEntitys(param);
            for (InstockProductEntity entity : entitys) {
                if (Objects.isNull(entity.getRefProductId())) {
                    isOld = true;
                    break;
                }
            }
        }
        return isOld;
    }

    /**
     * 更新采购合同产品相关属性
     *
     * @param purchaseProduct 采购合同产品
     */
    private void setProductParam(PurchaseProductEntity purchaseProduct) throws XbbException {
        ProductEntityExt product = productModel.getByKey(purchaseProduct.getProductId(), purchaseProduct.getCorpid());
        if (Objects.isNull(product)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        JSONObject dataList = product.getData();
        ProductEntityExt parentProduct = productModel.getByKey(dataList.getLong(ProductEnum.PARENT_ID.getAttr()), purchaseProduct.getCorpid());
        JSONObject productData = parentProduct.getData();
        String name = productData.getString(ProductEnum.NAME.getAttr());
        String productNo = productData.getString(ProductEnum.PRODUCT_NO.getAttr());
        // 规格用子产品的具体规格
        String specification = dataList.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
        String unit = productData.getString(ProductEnum.UNIT.getAttr());
        String thumbnail = productData.getString(ProductEnum.THUMBNAIL.getAttr());

        purchaseProduct.setProductName(StringUtil.isEmpty(name) ? "" :name);
        purchaseProduct.setProductNo(StringUtil.isEmpty(productNo)? "" : productNo);
        purchaseProduct.setProductSpecification(StringUtil.isEmpty(specification) ? "{}" : specification);
        purchaseProduct.setProductUnit(StringUtil.isEmpty(unit) ? "" : unit);
        purchaseProduct.setThumbnail(StringUtil.isEmpty(thumbnail) ? "" : thumbnail);
    }


    /**
     * 编辑情况下，更新采购合同入库状态
     * @param purchaseEntityExt 采购合同参数
     * @param isNew 是否新建
     * @date 2019/2/27 20:17
     * @author Jian.Wang
     */
    private void setPurchaseAllInComing(PurchaseEntityExt purchaseEntityExt, boolean isNew) throws XbbException {
        if (!isNew) {
            JSONObject purchaseProductList = purchaseEntityExt.getData();
            String corpid = purchaseEntityExt.getCorpid();
            Long purchaseId = purchaseEntityExt.getId();
            //采购合同关联未入库产品
            List<PurchaseProductEntity> purchaseProductEntityList = getSurplusProduct(corpid, purchaseId, null, null);
            if (purchaseProductEntityList.size() > 0) {
                //是否全部入库 0：否 1：是
                purchaseProductList.put(PurchaseEnum.ALL_INCOMING.getAttr(),0);
            } else {
                purchaseProductList.put(PurchaseEnum.ALL_INCOMING.getAttr(),1);
            }
            purchaseEntityExt.setData(purchaseProductList);
            purchaseModel.save(purchaseEntityExt);
        }
    }


    /**
     * 获取采购合同剩余未入库产品信息及数量
     *
     * @param corpid            公司id
     * @param purchaseId        采购合同id
     * @param purchaseEntityExt 此参数可以为null ，用于更新关联出库单id，更安全
     * @param instockIdList     此参数用来去除特定入库单，显示采购合同剩余入库产品，用于编辑入库单使用，可以为null
     * @return 采购合同未入库产品列表
     */
    @Override
     public List<PurchaseProductEntity> getSurplusProduct(String corpid, Long purchaseId, PurchaseEntityExt purchaseEntityExt, List<Long> instockIdList) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("purchaseSheetId", purchaseId);
        param.put("del", 0);
        //拿到采购合同的所有产品
        List<PurchaseProductEntity> purchaseProductEntityList = purchaseProductModel.findEntitys(param);

        List<Long> productIdIn = new ArrayList<>();
        for (PurchaseProductEntity entity : purchaseProductEntityList) {
            productIdIn.add(entity.getProductId());
        }
        Map<Long, ProductEntityExt> productMap = productModel.getProductMapByIdIn(corpid, productIdIn, null);


        PaasFormDataEsListVO paasFormDataEsListVO = instockService.getInstockListFromEs(corpid, purchaseId, InstockTypeEnum.PURCHASE_INSTOCK.getCode());
        List<PaasFormDataEntityExt> paasFormDataESList = paasFormDataEsListVO.getPaasFormDataESList();
        // 拿到该采购合同对应的所有入库单id
        List<Long> instockIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt instockEsEntity : paasFormDataESList) {
            instockIds.add(instockEsEntity.getDataId());
        }

        if (purchaseEntityExt != null) {
            // 根据已有的入库单重置数据，更安全
            JSONObject dataList = purchaseEntityExt.getData();
            dataList.put(PurchaseEnum.INSTOCK_ID.getAttr(), instockIds);
            purchaseEntityExt.setData(dataList);
        }

        // 这里去掉特定入库单
        instockModel.removeInstock(instockIdList, instockIds);

        instockIds.add(-1L);

        param.clear();
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("instockIdIn", instockIds);
        // 拿到所有的已入库产品
        List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(param);

        // 合并相同的产品(采购合同可以重复添加同一产品)
        Map<Long, PurchaseProductEntity> purchaseProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PurchaseProductEntity purchaseProduct : purchaseProductEntityList) {
            Long productId = purchaseProduct.getProductId();
            if (purchaseProductMap.containsKey(productId)) {
                PurchaseProductEntity mergePurchaseProduct = purchaseProductMap.get(productId);
                Double mergeNum = Arith.add(mergePurchaseProduct.getProductNum(), purchaseProduct.getProductNum());
                mergePurchaseProduct.setProductNum(mergeNum);
                Double totalPrice = Arith.add(mergePurchaseProduct.getProductPrice(), purchaseProduct.getProductPrice() * purchaseProduct.getProductNum());
                mergePurchaseProduct.setProductPrice(totalPrice);
                purchaseProductMap.put(productId, mergePurchaseProduct);
                String memo = mergePurchaseProduct.getMemo();
                if (StringUtils.isNotEmpty(purchaseProduct.getMemo())) {
                    memo += "/" + purchaseProduct.getMemo();
                    mergePurchaseProduct.setMemo(memo);
                }
            } else {
                purchaseProductMap.put(productId, purchaseProduct);
                purchaseProduct.setProductPrice(purchaseProduct.getProductPrice() * purchaseProduct.getProductNum());
            }
        }

        purchaseProductEntityList.clear();
        for (PurchaseProductEntity purchaseProduct : purchaseProductMap.values()) {
            if (purchaseProduct.getProductNum() != 0) {
                purchaseProduct.setProductPrice(Arith.div(purchaseProduct.getProductPrice(), purchaseProduct.getProductNum()));
            }
            ProductEntityExt product = productMap.get(purchaseProduct.getProductId());
            if (product != null) {
                JSONObject dataList = product.getData();
                if (null == dataList) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
                }
                purchaseProduct.setBarcode(dataList.getString(ProductEnum.BARCODE.getAttr()));
            }
            purchaseProductEntityList.add(purchaseProduct);
        }

        //把id相同的入库产品的数量叠加，然后采购合同的产品比较，判断采购合同里的产品是否已经全部入库
        Map<Long, Double> instockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (InstockProductEntity entity : instockProductEntityList) {
            Long productId = entity.getProductId();
            if (instockProductMap.get(productId) == null) {
                instockProductMap.put(productId, entity.getProductNum());
            } else {
                instockProductMap.put(productId,  Arith.add(entity.getProductNum(), instockProductMap.get(productId)));
            }
        }

        Iterator<PurchaseProductEntity> it = purchaseProductEntityList.iterator();
        while (it.hasNext()) {
            PurchaseProductEntity purchaseProductEntity = it.next();
            for (Map.Entry<Long, Double> entry : instockProductMap.entrySet()) {
                if (purchaseProductEntity.getProductId().equals(entry.getKey())) {
                    // 获取剩余未入库数量
                    double leftNum = Arith.sub(purchaseProductEntity.getProductNum(), entry.getValue());
                    if (Double.compare(leftNum, 0D) <= 0) {
                        // 如果采购合同产品数量少于已入库数量，那么就将该产品去掉不显示.（出现这种情况是因为采购合同重新编辑数量变少了）
                        it.remove();
                        break;
                    } else {
                        purchaseProductEntity.setProductNum(leftNum);
                    }
                }
            }
        }
        return purchaseProductEntityList;
    }

    /**
     * 获取采购合同已入库的所有产品信息(用于对采购合同编辑时限制产品数量使用)
     *
     * @param corpid          公司id
     * @param purchaseId 采购合同ID
     * @author Jian.Wang
     * @date 2019/2/21 17:19
     */
    @Override
    public List<PurchaseProductEntity> getAlreadyStoreProduct(String corpid, Long purchaseId) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("purchaseSheetId", purchaseId);
        param.put("del", 0);
        //拿到采购合同的所有产品
        List<PurchaseProductEntity> purchaseProductEntityList = purchaseProductModel.findEntitys(param);

        List<Long> productIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PurchaseProductEntity entity : purchaseProductEntityList) {
            productIdIn.add(entity.getProductId());
        }
        if (!productIdIn.isEmpty()) {
            Map<Long, ProductEntityExt> productMap = productModel.getProductMapByIdIn(corpid, productIdIn, null);
            for (PurchaseProductEntity entity : purchaseProductEntityList) {
                ProductEntityExt product = productMap.get(entity.getProductId());
                if (product == null) {
                    continue;
                }
                JSONObject dataList = product.getData();
                if (null != dataList) {
                    entity.setBarcode(dataList.getString(ProductEnum.BARCODE.getAttr()));
                }
            }
        }

        PaasFormDataEsListVO paasFormDataEsListVO = instockService.getInstockListFromEs(corpid, purchaseId, 1);
        List<PaasFormDataEntityExt> paasFormDataESList = paasFormDataEsListVO.getPaasFormDataESList();
        // 拿到该采购合同对应的所有入库单id
        List<Long> instockIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt instockEsEntity : paasFormDataESList) {
            instockIds.add(instockEsEntity.getDataId());
        }
        instockIds.add(-1L);

        param.clear();
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("instockIdIn", instockIds);
        //拿到所有的已入库产品
        List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(param);

        //合并相同的产品(采购合同可以重复添加同一产品)
        Map<Long, PurchaseProductEntity> purchaseProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //重复productId产品
        Set<Long> sameProductSet = new HashSet<>();
        for (PurchaseProductEntity purchaseProduct : purchaseProductEntityList) {
            Long productId = purchaseProduct.getProductId();
            if (purchaseProductMap.containsKey(productId)) {
                PurchaseProductEntity mergePurchaseProduct = purchaseProductMap.get(productId);
                mergePurchaseProduct.setProductNum(Arith.add(mergePurchaseProduct.getProductNum(), purchaseProduct.getProductNum()));
                mergePurchaseProduct.setProductPrice(Arith.add(mergePurchaseProduct.getProductPrice(), purchaseProduct.getProductNum() * purchaseProduct.getProductPrice()));
                String memo = mergePurchaseProduct.getMemo();
                if (StringUtils.isNotEmpty(purchaseProduct.getMemo())) {
                    memo += "/" + purchaseProduct.getMemo();
                    mergePurchaseProduct.setMemo(memo);
                }
                purchaseProductMap.put(productId, mergePurchaseProduct);
                sameProductSet.add(productId);
            } else {
                purchaseProductMap.put(productId, purchaseProduct);
            }
        }

        purchaseProductEntityList.clear();
        for (PurchaseProductEntity purchaseProduct : purchaseProductMap.values()) {
            if (sameProductSet.contains(purchaseProduct.getProductId()) && purchaseProduct.getProductNum() != 0) {
                purchaseProduct.setProductPrice(Arith.div(purchaseProduct.getProductPrice(), purchaseProduct.getProductNum()));
            }
            purchaseProductEntityList.add(purchaseProduct);
        }

        //将已入库相同id的产品的数量相加
        Map<Long, Double> instockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (InstockProductEntity entity : instockProductEntityList) {
            if (instockProductMap.get(entity.getProductId()) == null) {
                instockProductMap.put(entity.getProductId(), entity.getProductNum());
            } else {
                instockProductMap.put(entity.getProductId(),
                        Arith.add(entity.getProductNum(), instockProductMap.get(entity.getProductId())));
            }
        }
        for (int i = purchaseProductEntityList.size() - 1; i > -1; i--) {
            PurchaseProductEntity purchaseProduct = purchaseProductEntityList.get(i);
            Double instockProductNum = instockProductMap.get(purchaseProduct.getProductId());
            if (instockProductNum != null) {
                //采购产品已部分或全部入库则将数量更改为入库数量
                purchaseProduct.setProductNum(instockProductNum);
            } else {
                //采购产品未入库则删除
                purchaseProductEntityList.remove(purchaseProduct);
            }
        }
        return purchaseProductEntityList;
    }



    /**
     * 批量一键采购
     *
     * @param handlerExplainBatchLinkItemDTO 入参
     * @throws XbbException 异常
     */
    @Override
    public void formatBatchLinkAddExplain(HandlerExplainBatchLinkItemDTO handlerExplainBatchLinkItemDTO) throws XbbException {
        String corpid = handlerExplainBatchLinkItemDTO.getCorpid();
        Integer linkBusinessType = handlerExplainBatchLinkItemDTO.getLinkBusinessType();
        Integer sourceBusinessType = handlerExplainBatchLinkItemDTO.getSourceBusinessType();
        // 智能补货批量一键采购时传入的产品数据
        List<OneKeyProduceProductPojo> linkList = handlerExplainBatchLinkItemDTO.getProductList();
        List<PaasFormDataEntityExt> paasFormDataEntityExts = handlerExplainBatchLinkItemDTO.getPaasFormDataEntityExts();
        List<Long> linkDataIdIn = new ArrayList<>();
        paasFormDataEntityExts.forEach(paasFormDataEntityExt -> linkDataIdIn.add(paasFormDataEntityExt.getId()));
        List<FieldAttrEntity> explainList = handlerExplainBatchLinkItemDTO.getExplainList();
        FieldAttrEntity supplierField = new FieldAttrEntity();
        FieldAttrEntity productField = new FieldAttrEntity();
        FieldAttrEntity moneyField = new FieldAttrEntity();
        FieldAttrEntity productTotalField = new FieldAttrEntity();
        for(FieldAttrEntity fieldAttrEntity :explainList) {
            if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.SUPPLIER_ID.getAttr())) {
                supplierField = fieldAttrEntity;
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.PRODUCT.getAttr())) {
                productField = fieldAttrEntity;
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.TOTAL_MONEY.getAttr())) {
                moneyField = fieldAttrEntity;
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.PRODUCT_TOTAL.getAttr())) {
                productTotalField = fieldAttrEntity;
            }
        }
        Map<Long,String> contractNoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionsUtil.isNotEmpty(linkDataIdIn)){
            List<ContractEntityExt> contractEntityExtList = contractModel.findEntitysByIdIn(corpid,0,linkDataIdIn);
            if (CollectionsUtil.isNotEmpty(contractEntityExtList)){
                contractEntityExtList.forEach(item -> contractNoMap.put(item.getId(),item.getSerialNo()));
            }
        }
        explainHelp.formatSelectProductExplains(productField, XbbRefTypeEnum.PURCHASE, corpid, OperatePageEnum.NEW.getCode(), false);
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(linkBusinessType);
        Set<Long> productIds = new HashSet<>();
        LinkedHashMap<Long, ContractProductEntity> contractProductEntityMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Double totalProductMoney = 0D;
        Map<Long,PaasFormDataEntityExt> lackProductMap;
        Map<Long,Double> rateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> contractProductIdList = new ArrayList<>();
        Map<Long,Double> productNumMap = new HashMap<>();
        linkList.forEach(item ->{
            contractProductIdList.add(item.getId());
            productNumMap.put(item.getId(),item.getNum());
        });
        // 查询出符合待采购的合同产品数据
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid",corpid);
        param.put("del",DelEnum.NORMAL.getDel());
        if (Objects.equals(redundantTemplateTypeEnum,RedundantTemplateTypeEnum.CONTRACT)){
            param.put("contractIdIn",linkDataIdIn);
        }
        param.put("status",0);
        param.put(ParameterConstant.ORDER_BY_STR, "contract_id, sort DESC");
        if (CollectionsUtil.isNotEmpty(contractProductIdList)){
            param.put("idIn",contractProductIdList);
        }
        List<ContractProductEntity> contractProductEntityList = contractProductModel.findEntitys(param);
        // 一键采购排序
        if (CollectionUtils.isNotEmpty(contractProductEntityList) && Objects.equals(redundantTemplateTypeEnum,RedundantTemplateTypeEnum.CONTRACT)){
            Map<Long,List<ContractProductEntity>> contractProductMap = new HashMap<>();
            for (ContractProductEntity contractProductEntity : contractProductEntityList) {
                Long cid = contractProductEntity.getContractId();
                if (contractProductMap.containsKey(cid)){
                    List<ContractProductEntity> entityList = contractProductMap.get(cid);
                    entityList.add(contractProductEntity);
                    contractProductMap.put(cid,entityList);
                }else {
                    List<ContractProductEntity> productEntityList = new ArrayList<>();
                    productEntityList.add(contractProductEntity);
                    contractProductMap.put(cid,productEntityList);
                }
            }
            contractProductEntityList.clear();
            for (Long cid : linkDataIdIn) {
                List<ContractProductEntity> entityList = contractProductMap.get(cid);
                entityList.sort(Comparator.comparing(obj -> obj.getSort()));
                contractProductEntityList.addAll(entityList);
            }
        }
        List<String> onlyKeyList = new ArrayList<>();
        for (ContractProductEntity contractProductEntity : contractProductEntityList) {
            onlyKeyList.add(contractProductEntity.getId() + "_" + contractProductEntity.getProductId());
        }
        List<PurchaseBalanceEntity> purchaseBalanceEntityList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(onlyKeyList)){
            purchaseBalanceEntityList = purchaseBalanceModel.findByOnlyKeys(corpid, onlyKeyList);
        }

        // 超发库存map key = contractid_productid  value=超发库存总量
        Map<String, Double> exceedStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if  (CollectionsUtil.isNotEmpty(purchaseBalanceEntityList)){
            purchaseBalanceEntityList.forEach(item -> exceedStockMap.put(item.getOnlyKey(),item.getExceedStockNum()));
        }
        List<ContractProductEntity> contractProductEntitys = new ArrayList<>();
        // 获取该合同下所有的采购数据
        // key=contractid_product_id  value = 采购数据
        // 已和产品确认 没有批量一键采购
        Map<String, Double> purchaseByContractMap = saasListHelp.getPurchaseByContract(corpid, linkDataIdIn);
        Map<String,Double> shortageQuantityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 封装此次智能补货一键采购的数量
        Map<Long ,Double> smartProductNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        switch (redundantTemplateTypeEnum) {
            case CONTRACT:
//                List<ContractProductEntity> contractProductEntityList = contractProductModel.getContractProductByContractIdIn(corpid, 0, linkDataIdIn);
//                List<ContractProductEntity> contractProductEntityList = contractProductModel.getContractProductByContractIdIn(corpid, linkDataIdIn);
//                List<String> onlyKeyList = new ArrayList<>();

                if (CollectionsUtil.isNotEmpty(onlyKeyList)){
                    Iterator<ContractProductEntity> iterator = contractProductEntityList.iterator();
                    while (iterator.hasNext()) {
                        ContractProductEntity contractProductEntity = iterator.next();
                        String onlyKey = contractProductEntity.getId() + "_" + contractProductEntity.getProductId();
                        double purchaseSumNum = 0D;
                        if(!purchaseByContractMap.isEmpty() && purchaseByContractMap.containsKey(onlyKey)){
                            purchaseSumNum = purchaseByContractMap.get(onlyKey);
                        }
                        // 超发库存总量
                        double exceedNum = 0D;
                        if (!exceedStockMap.isEmpty() && exceedStockMap.containsKey(onlyKey)){
                            exceedNum = exceedStockMap.get(onlyKey);
                        }
                        // 新公式: 建议采购量 = 合同总量 - 采购总量 - 超发库存总量
                        Double shortageQuantity = Arith.sub(contractProductEntity.getProductNum(),Arith.add(purchaseSumNum,exceedNum));
                        if (shortageQuantity <= 0){
                            iterator.remove();
                        }
                        shortageQuantityMap.put(onlyKey,shortageQuantity);
                    }
                }
                for (ContractProductEntity contractProductEntity : contractProductEntityList) {
                    productIds.add(contractProductEntity.getProductId());
                }
                lackProductMap = productService.getProductMapByIdIn(productIds, corpid, null);
                for (ContractProductEntity entity : contractProductEntityList) {
                    Long cId = entity.getContractId();
                    Long pid = entity.getProductId();
                    String onlyKey = entity.getId() + "_" + pid;
                    // 建议采购量
                    double shortageQuantity = 0d;
                    if (shortageQuantityMap.containsKey(onlyKey)){
                        shortageQuantity = shortageQuantityMap.get(onlyKey);
                    }
                    entity.setSumNum(Arith.sub(entity.getProductNum(),entity.getContractOutstockNum()));
                    double rate = Objects.isNull(entity.getRate()) ? 1D : entity.getRate();
                    rateMap.put(entity.getId(), rate);
                    if (Objects.nonNull(entity.getBusinessUnit())) {
//                        entity.setProductUnit(entity.getBusinessUnit().toString());
                    }
                    Long productId = entity.getProductId();
                    double cost = 0D;
                    if (lackProductMap.containsKey(productId)) {
                        PaasFormDataEntityExt paasFormDataEntityExt = lackProductMap.get(productId);
                        cost = Arith.mul(paasFormDataEntityExt.getData().getDoubleValue(ProductEnum.COST.getAttr()), rate);
                    }
                    // TODO 合计计算后面找产品确认
                    totalProductMoney = totalProductMoney + Arith.div(shortageQuantity, rate) * cost;
                    // 采购数量都按照基本单位
                    entity.setProductNum(shortageQuantity);
                    entity.getData().put(ContractProductEnum.NUM.getAttr(),entity.getProductNum());
                    if (contractProductEntityMap.containsKey(productId)){
                        ContractProductEntity contractProductEntity = contractProductEntityMap.get(productId);
//                        contractProductEntity.setProductNum(contractProductEntity.getProductNum() + entity.getProductNum());
                        contractProductEntityMap.put(productId,contractProductEntity);
                    } else {
                        entity.setData(null);
                        contractProductEntityMap.put(productId,entity);
                    }
                    contractProductEntitys.add(entity);
                }
                break;
            case PRODUCT:
                // 此次一键采购的所有产品信息
                List<Long> smartProductIdList = new ArrayList<>();

                // 智能补货特殊处理
                if (Objects.equals(XbbRefTypeEnum.SMART_REPLENISHMENT.getCode(),sourceBusinessType)){
                    smartProductIdList.add(-1L);
                    if (!linkList.isEmpty()){
                        linkList.forEach(item ->{
                            productIds.add(item.getId());
                            smartProductIdList.add(item.getId());
                            smartProductNumMap.put(item.getId(),item.getNum());
                        });
                    }
                    //  为了不影响原逻辑 封装一个假的合同产品
                    if (!smartProductNumMap.isEmpty()){
                        for(Map.Entry<Long, Double> entry : smartProductNumMap.entrySet()){
                            ContractProductEntity contractProductEntity = new ContractProductEntity();
                            contractProductEntity.setProductId(entry.getKey());
                            contractProductEntity.setProductNum(entry.getValue());
                            contractProductEntityMap.put(entry.getKey(), contractProductEntity);
                            contractProductEntitys.add(contractProductEntity);
                            productIds.add(entry.getKey());
                        }
                    }
                    break;
                }
                List<Long> contractIdIn = new ArrayList<>();
                for (ContractProductEntity contractProductEntity : contractProductEntityList) {
                    productIds.add(contractProductEntity.getProductId());
                    contractIdIn.add(contractProductEntity.getContractId());
                }
                SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                BoolQueryBuilder queryBuilder = boolQuery();
                queryBuilder.filter(termQuery("corpid.keyword", corpid));
                queryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
                queryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), contractIdIn));
                queryBuilder.filter(termQuery(ContractEnum.getAttrConnectData(ContractEnum.ARCHIVED), 1));
                queryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_CONTRACT.getType()));
                searchSourceBuilder.query(queryBuilder);
                List<PaasFormDataEntityExt> list = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_CONTRACT, Collections.singletonList(FieldTypeEnum.DATAID.getAlias()), 1, contractIdIn.size());
                List<Long> archivedContractIds = new ArrayList<>();
                if (CollectionsUtil.isNotEmpty(list)) {
                    list.forEach(paasFormDataEntityExt -> archivedContractIds.add(paasFormDataEntityExt.getDataId()));
                }
                Iterator<ContractProductEntity> iterator = contractProductEntityList.iterator();
                while (iterator.hasNext()) {
                    ContractProductEntity contractProductEntity = iterator.next();
                    if (archivedContractIds.contains(contractProductEntity.getContractId())) {
                        iterator.remove();
                    }
                }
                lackProductMap = productService.getProductMapByIdIn(productIds, corpid, null);
                for (ContractProductEntity entity : contractProductEntityList) {
                    Long productId = entity.getProductId();
                    // 建议采购量为0的产品不放入一键采购自动带入的产品中
                    // 建议采购量
                    double advisePurchaseNum = 0d;
                    if (CollectionsUtil.isNotEmpty(onlyKeyList)){
                        String onlyKey = entity.getId() + "_" + entity.getProductId();
                        // 建议采购量用前端传入的数量
                        advisePurchaseNum = productNumMap.getOrDefault(entity.getId(),0D);
                        shortageQuantityMap.put(onlyKey,advisePurchaseNum);
                    }
                    double rate = Objects.isNull(entity.getRate()) ? 1D : entity.getRate();
                    rateMap.put(entity.getId(), rate);
                    if (Objects.nonNull(entity.getBusinessUnit())) {
//                        entity.setProductUnit(entity.getBusinessUnit().toString());
                    }
                    double cost = 0D;
                    if (lackProductMap.containsKey(productId)) {
                        PaasFormDataEntityExt paasFormDataEntityExt = lackProductMap.get(productId);
                        cost = paasFormDataEntityExt.getData().getDoubleValue(ProductEnum.COST.getAttr());
                    }
                    totalProductMoney = Arith.add(totalProductMoney,Arith.mul(advisePurchaseNum , cost));
//                    entity.setProductNum(Arith.div(advisePurchaseNum,rate));
                    entity.setProductNum(productNumMap.getOrDefault(entity.getId(),0D));
                    if (contractProductEntityMap.containsKey(productId)){
                        ContractProductEntity contractProductEntity = contractProductEntityMap.get(productId);
//                        contractProductEntity.setProductNum(contractProductEntity.getProductNum() + entity.getProductNum());
                        contractProductEntityMap.put(productId,contractProductEntity);
                    } else {
                        entity.setData(null);
                        contractProductEntityMap.put(productId,entity);
                    }
                    contractProductEntitys.add(entity);
                }
                break;
            default:
                break;
        }
        JSONObject productData = new JSONObject();
        contractService.formatProduct4Show3(contractProductEntitys,productData,UpdateDataTypeEnum.LINK_ADD);
        JSONArray productArray = formDataValidateProductHelp.otherProductToAnother(productData,productField,PurchaseEnum.PRODUCT.getAttr(),ContractEnum.PRODUCT.getAttr(),corpid, handlerExplainBatchLinkItemDTO.getLoginUser(), XbbRefTypeEnum.PURCHASE.getCode(), handlerExplainBatchLinkItemDTO.getLinkBusinessType());
        //TODO 补一下单价单位
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),productIds));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
        List<PaasFormDataEntityExt> productList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder,PaasFormDataEntityExt.class,Arrays.asList(FieldTypeEnum.DATAID.getAlias(),ProductEnum.getAttrConnectData(ProductEnum.COST),ProductEnum.getAttrConnectData(ProductEnum.UNIT), FieldTypeEnum.OWNERID.getAlias(), FieldTypeEnum.CREATORID.getAlias()));
        Map<Long,PaasFormDataEntityExt> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        productList.forEach(item -> productMap.put(item.getDataId(),item));
        if (Objects.equals(XbbRefTypeEnum.SMART_REPLENISHMENT.getCode(),sourceBusinessType) && CollectionUtils.isNotEmpty(productList)){
            for (PaasFormDataEntityExt item : productList) {
                Long productId = item.getDataId();
                Double cost = item.getData().getDouble(ProductEnum.COST.getAttr());
                Double num = smartProductNumMap.getOrDefault(productId, 0D);
                totalProductMoney = Arith.add(totalProductMoney,Arith.mul(num , cost));
            }
        }

        ProductFieldPojo costField = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_COST,ProductEnum.COST.getAttr(), corpid);
        ProductFieldPojo priceField = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_PRICE,ProductEnum.PRICE.getAttr(), corpid);
        Integer accuracy = priceField.getAccuracy();
        boolean costVisible = true;
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        handlerExplainDTO.setLoginUser(handlerExplainBatchLinkItemDTO.getLoginUser());
        handlerExplainDTO.setUserId(handlerExplainBatchLinkItemDTO.getUserId());
        FieldAttrEntity costFieldAttr = new FieldAttrEntity();
        BeanUtil.copyProperties(costField, costFieldAttr);
        for (int i = 0;i < productArray.size();i++){
            JSONObject jsonObject = productArray.getJSONObject(i);
            Long contid = jsonObject.getLong("contractId");
            PaasFormDataEntityExt productEntityExt = null;
            Long productSubId = jsonObject.getLong(BusinessConstant.RELY_PRODUCT_SUB_ID);
            if (productMap.containsKey(jsonObject.getJSONObject(PurchaseProductEnum.PRODUCT.getAttr()).getLong("dataId"))){
                Long dataId = jsonObject.getJSONObject(PurchaseProductEnum.PRODUCT.getAttr()).getLong("dataId");
                productEntityExt = productMap.get(dataId);
                handlerExplainDTO.setOwnerId(Arrays.asList(productEntityExt.getOwnerId()));
                handlerExplainDTO.setCreatorId(productEntityExt.getCreatorId());
                costVisible = !ExplainUtil.isFieldNeedHide(costFieldAttr,handlerExplainDTO);
                jsonObject.put(PurchaseProductEnum.PURCHASE_PRICE.getAttr(),costVisible ? attrDecimalPrecisionHelper.setPrecision(productEntityExt.getData().getDouble(ProductEnum.COST.getAttr()),accuracy) : 0D);
                jsonObject.put(PurchaseProductEnum.SUBTOTAL.getAttr(),attrDecimalPrecisionHelper.setPrecision(Arith.mul(jsonObject.getDouble(PurchaseProductEnum.PURCHASE_PRICE.getAttr()) , jsonObject.getDouble(PurchaseProductEnum.NUM.getAttr())),accuracy));
                JSONObject sellingMap = jsonObject.getJSONObject(ProductConstant.SELLING_PRICE_MAP);
                if (Objects.nonNull(sellingMap)) {
                    sellingMap.put(PurchaseProductEnum.PURCHASE_PRICE.getAttr(), jsonObject.get(PurchaseProductEnum.PURCHASE_PRICE.getAttr()));
                }
                // 关联新建添加合同编号
                jsonObject.put(PurchaseProductEnum.CONTRACT_NO.getAttr(),contractNoMap.get(contid));
                jsonObject.put("contractId",contid);
            }
            for (Map.Entry<String, Object> entry : productArray.getJSONObject(i).entrySet()){
                if (ProductEnum.UNIT.getAttr().equals(entry.getKey())){
                    if (Objects.isNull(entry.getValue())){
                        String value = null;
                        JSONObject obj = productEntityExt.getData();
                        if (Objects.nonNull(obj)){
                            value= obj.getString(ProductEnum.UNIT.getAttr());
                        }
                        productArray.getJSONObject(i).put(ProductEnum.UNIT.getAttr(),value);
                    }

                    break;
                }
            }
        }
        productField.setDefaultAttr(saasUpdateHelp.setDefaultValue(productArray));
//        Double totalProductMoney = products.getJSONObject(BusinessConstant.OTHERS).getDouble(BusinessConstant.TOTAL_PRODUCT_MONEY);
        DefaultAttrPoJo defaultAttr = moneyField.getDefaultAttr();
        if(costVisible){
            defaultAttr.setLinkFormValue(attrDecimalPrecisionHelper.setPrecision(totalProductMoney, moneyField.getAccuracy()));
            defaultAttr.setUseLinkValue(BasicConstant.ONE);
        }
        DefaultAttrPoJo productTotalAttr = productTotalField.getDefaultAttr();
        productTotalAttr = productTotalAttr == null ? new DefaultAttrPoJo() : productTotalAttr;
        if (costVisible){
            productTotalAttr.setLinkFormValue(totalProductMoney);
            productTotalAttr.setUseLinkValue(BasicConstant.ONE);
        }
        productTotalField.setDefaultAttr(productTotalAttr);
        setSupplierDefaultValue(corpid, new ArrayList<>(productIds), supplierField, handlerExplainBatchLinkItemDTO.getPaasFormExplainEntity().getFormId());
    }

    /**
     * Description: 关联新建时格式化解释
     *
     * @param handlerExplainInLinkItemDTO
     * @return void
     * @throws XbbException XbbException
     * @author 陈有利
     * @date 2019/5/23 17:22
     * @since v1.0
     */
    @Override
    public void formatLinkAddExplain(HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        Integer linkBusinessType = handlerExplainInLinkItemDTO.getLinkBusinessType();
        Integer sourceBusinessType = handlerExplainInLinkItemDTO.getSourceBusinessType();
        JSONObject linkFormData = handlerExplainInLinkItemDTO.getLinkFormData();
        List<FieldAttrEntity> explainList = handlerExplainInLinkItemDTO.getExplainList();
        PaasFormDataEntityExt paasFormDataEntityExt = handlerExplainInLinkItemDTO.getPaasFormDataEntityExt();
        String corpid = paasFormDataEntityExt.getCorpid();

        FieldAttrEntity supplierField = new FieldAttrEntity();
        FieldAttrEntity productField = new FieldAttrEntity();
        FieldAttrEntity moneyField = new FieldAttrEntity();
        FieldAttrEntity productTotalField = new FieldAttrEntity();
        for(FieldAttrEntity fieldAttrEntity :explainList) {
            // 供应商实体
            if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.SUPPLIER_ID.getAttr())) {
                supplierField = fieldAttrEntity;
            }
            // 采购产品实体
            if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.PRODUCT.getAttr())) {
                productField = fieldAttrEntity;
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.TOTAL_MONEY.getAttr())) {
                // 采购金额
                moneyField = fieldAttrEntity;
            }
            // 产品合计
            if (Objects.equals(fieldAttrEntity.getAttr(), PurchaseEnum.PRODUCT_TOTAL.getAttr())) {
                productTotalField = fieldAttrEntity;
            }
        }

        List<OneKeyProduceProductPojo> linkList = handlerExplainInLinkItemDTO.getProductList();

        JSONArray productList = new JSONArray();
        List<Long> productIds = new ArrayList<>();
        List<Long> contractProductIds = new ArrayList<>();
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(linkBusinessType);
        switch (redundantTemplateTypeEnum) {
            case CONTRACT:
                linkList.forEach(link -> contractProductIds.add(link.getId()));
                for(OneKeyProduceProductPojo oneKeyProduceProductPojo : linkList){
                    JSONObject product = new JSONObject();
                    product.put(PurchaseProductEnum.PRODUCT.getAttr(), oneKeyProduceProductPojo.getId());
                    product.put(PurchaseProductEnum.NUM.getAttr(), oneKeyProduceProductPojo.getNum());
                    product.put(PurchaseProductEnum.UNIT.getAttr(), oneKeyProduceProductPojo.getUnit());
                    product.put(MultiUnitConstant.RATE, oneKeyProduceProductPojo.getRate() == null ? 1D : oneKeyProduceProductPojo.getRate());
                    if (Objects.equals(XbbRefTypeEnum.PURCHASE.getCode(),handlerExplainInLinkItemDTO.getBusinessType())){
                        ContractEntityExt contractEntityExt = contractModel.getByKey(linkDataId, corpid);
                        if (Objects.nonNull(contractEntityExt)){
                            product.put("contractId",linkDataId);
                            product.put("contractProductId",oneKeyProduceProductPojo.getId());
                            product.put(PurchaseProductEnum.CONTRACT_NO.getAttr(),contractEntityExt.getSerialNo());
                        }
                    }
                    productList.add(product);
                }
                break;
            case PRODUCT:
                // 智能补货特殊处理
                if (Objects.equals(XbbRefTypeEnum.SMART_REPLENISHMENT.getCode(),sourceBusinessType)){
                    // 此次一键采购的所有产品信息
                    List<Long> smartProductIdList = new ArrayList<>();
                    // 封装此次一键采购的数量
                    Map<Long ,Double> smartProductNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    smartProductIdList.add(-1L);
                    if (!linkList.isEmpty()){
                        linkList.forEach(item ->{
                            productIds.add(item.getId());
                            smartProductIdList.add(item.getId());
                            smartProductNumMap.put(item.getId(),item.getNum());
                        });
                    }
                    if (!smartProductNumMap.isEmpty()){
                        for(Map.Entry<Long, Double> entry : smartProductNumMap.entrySet()){
                            JSONObject productObj = new JSONObject();
                            productObj.put(PurchaseProductEnum.PRODUCT.getAttr(), entry.getKey());
                            productObj.put(PurchaseProductEnum.NUM.getAttr(), entry.getValue());
                            productList.add(productObj);
                        }
                    }
                    break;
                }
                List<Long> idList = new ArrayList<>();
                idList.add(-1L);
                List<ContractProductEntity> productContractEntityList;
                Map<Long ,Double> productNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put("corpid", corpid);
                params.put("del", DelEnum.NORMAL.getDel());
                if (Objects.nonNull(linkDataId)){
                    params.put("contractId", linkDataId);
                }
                params.put("type", ContractProductTypeEnum.CONTNRACT.getCode());
                params.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
                if(!linkList.isEmpty()) {
                    linkList.forEach(link -> {
                        idList.add(link.getId());
                        productNumMap.put(link.getId(),link.getNum());
                    });
                    params.put("productIdIn", idList);
//                    productContractEntityList = contractProductModel.findEntitys(params);
                    Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put("idIn",idList);
                    param.put("corpid",corpid);
                    param.put("del",0);
                    productContractEntityList = contractProductModel.findEntitys(param);

                } else{
//                    idList.add(linkDataId);
//                    productContractEntityList = contractProductModel.getContractProductByContractIdIn(corpid, 0, idList);
                    productContractEntityList = contractProductModel.findEntitys(params);
                }
                Map<Long, Long> product =  new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                productContractEntityList.forEach(productContractEntity -> productIds.add(productContractEntity.getProductId()));
                for(ContractProductEntity productContractEntity : productContractEntityList){
                    Long proId = productContractEntity.getProductId();
//                    Double num = productContractEntity.getSumNum() - productContractEntity.getTotal();
                    Double num = productNumMap.getOrDefault(productContractEntity.getId(),0D);
//                    if (product.containsKey(proId)) {
//                        num = Arith.add(num, product.get(proId));
//                    }
                    product.put(productContractEntity.getId(), proId);
                }
                String serialNo = "";
                if (Objects.nonNull(linkDataId)){
                    ContractEntityExt byKey = contractModel.getByKey(linkDataId, corpid);
                    if (Objects.nonNull(byKey)){
                        serialNo = byKey.getSerialNo();
                    }
                }
                for(Map.Entry<Long, Long> entry : product.entrySet()){
                    JSONObject productObj = new JSONObject();
                    productObj.put(PurchaseProductEnum.PRODUCT.getAttr(), entry.getValue());
                    productObj.put(PurchaseProductEnum.NUM.getAttr(), productNumMap.getOrDefault(entry.getKey(),0D));
                    productObj.put("contractId",linkDataId);
                    productObj.put("contractProductId",entry.getKey());
                    productObj.put(PurchaseProductEnum.CONTRACT_NO.getAttr(),serialNo);
                    productList.add(productObj);
                }
                break;
            case SUPPLIER:
                String supplierName = FastJsonHelper.getStringOrDefaultFromFormData(linkFormData, SupplierEnum.SUPPLIER_NAME.getAttr(), "");
                supplierField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, supplierName, corpid, XbbRefTypeEnum.SUPPLIER,XbbRefTypeEnum.PREPAY_BALANCE));
                //获取该供应商的供货产品
                List<SupplierProductEntity> supplierProducts = supplierProductModel.getSupplierProductBySupplierId(corpid, linkDataId);
                if(CollectionsUtil.isNotEmpty(supplierProducts)){
                    supplierProducts.forEach(item -> {
                        productIds.add(item.getProductId());
                    });
                }
                break;
            default:
                throw new XbbException(TemplateErrorCodeEnum.API_ERROR_350006);
        }
        JSONObject productData = new JSONObject();
        Double totalProductMoney = formatLinkAdd4Show(productList,corpid,handlerExplainInLinkItemDTO.getLoginUser());
        productData.put(PurchaseEnum.PRODUCT.getAttr(),productList);
        JSONArray productArray = formDataValidateProductHelp.otherProductToAnother(productData,productField,PurchaseEnum.PRODUCT.getAttr(),PurchaseEnum.PRODUCT.getAttr(),corpid, handlerExplainInLinkItemDTO.getLoginUser(), handlerExplainInLinkItemDTO.getBusinessType(), handlerExplainInLinkItemDTO.getLinkBusinessType());
        productField.setDefaultAttr(saasUpdateHelp.setDefaultValue(productArray));
        DefaultAttrPoJo defaultAttr = moneyField.getDefaultAttr();
        defaultAttr = defaultAttr == null ? new DefaultAttrPoJo() : defaultAttr;
        defaultAttr.setLinkFormValue(attrDecimalPrecisionHelper.setPrecision(totalProductMoney, moneyField.getAccuracy()));
        defaultAttr.setUseLinkValue(BasicConstant.ONE);
        moneyField.setDefaultAttr(defaultAttr);
        // 产品合计默认值
        DefaultAttrPoJo productTotalAttr = productTotalField.getDefaultAttr();
        productTotalAttr = productTotalAttr == null ? new DefaultAttrPoJo() : productTotalAttr;
        productTotalAttr.setLinkFormValue(attrDecimalPrecisionHelper.setPrecision(totalProductMoney, productTotalField.getAccuracy()));
        productTotalAttr.setUseLinkValue(BasicConstant.ONE);
        productTotalField.setDefaultAttr(productTotalAttr);
        setSupplierDefaultValue(corpid, productIds, supplierField, handlerExplainInLinkItemDTO.getPaasFormExplainEntity().getFormId());
    }

    /**
     * 采购合同关联新建产品格式化
     * @param productList
     * @param corpid
     * @param loginUser
     * @return
     * @throws XbbException
     */
    private Double formatLinkAdd4Show(JSONArray productList, String corpid, UserVO loginUser) throws XbbException {
        List<Long> productIdList = new ArrayList<>();
        for (int i = 0;i < productList.size();i++){
            JSONObject jsonObject = productList.getJSONObject(i);
            productIdList.add(jsonObject.getLong(PurchaseProductEnum.PRODUCT.getAttr()));
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),productIdList));
        boolQueryBuilder.filter(termQuery("del",0));
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder,PaasFormDataEntityExt.class,Arrays.asList(FieldTypeEnum.DATAID.getAlias(),ProductEnum.getAttrConnectData(ProductEnum.COST),ProductEnum.getAttrConnectData(ProductEnum.UNIT),ProductEnum.CREATOR_ID.getAttr(),"ownerId",ProductEnum.getAttrConnectData(ProductEnum.ENABLE_MULTI_UNIT)));
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
        String explains = paasFormExplainEntity.getExplains();
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explains);
        FieldAttrEntity costfieldAttr = explainMap.getOrDefault(SelectProductEnum.COST.getAttr(),new FieldAttrEntity());
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        handlerExplainDTO.setLoginUser(loginUser);
        handlerExplainDTO.setUserId(loginUser.getUserId());
        Map<Long,Double> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,String> productUnitMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Integer enableMutilUnit;
        Map<Long, MultiUnitItemPoJo> groupBaseUnitMap = relativeProductHelp.getGroupBaseUnitMap(corpid);
        for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList){
            Double price = 0D;
            handlerExplainDTO.setCreatorId(entityExt.getCreatorId());
            handlerExplainDTO.setOwnerId(Arrays.asList(entityExt.getOwnerId()));
            Boolean costField = ExplainUtil.isFieldNeedHide(costfieldAttr, handlerExplainDTO);
            if (!costField && Objects.nonNull(entityExt.getData().getDouble(ProductEnum.COST.getAttr()))) {
                price = entityExt.getData().getDouble(ProductEnum.COST.getAttr());
            }
            String unit =  entityExt.getData().getString(ProductEnum.UNIT.getAttr());
            enableMutilUnit = getIntegerOrDefaultFromFormData(entityExt.getData(), ProductEnum.ENABLE_MULTI_UNIT.getAttr(), 0);
            if (Objects.equals(enableMutilUnit, 1)) {
                productUnitMap.put(entityExt.getDataId(), Objects.toString(groupBaseUnitMap.getOrDefault(Long.parseLong(unit), new MultiUnitItemPoJo()).getBaseValue(), ""));
            } else {
                productUnitMap.put(entityExt.getDataId(),unit);
            }
            productMap.put(entityExt.getDataId(),price);
        }
        Iterator<Object> iterator = productList.iterator();
        Double totalMoney = 0D;
        while (iterator.hasNext()){
            double money = 0D;
            JSONObject jsonObject = (JSONObject) iterator.next();
            Long productId = jsonObject.getLong(PurchaseProductEnum.PRODUCT.getAttr());
//            String unit = jsonObject.getString(PurchaseProductEnum.UNIT.getAttr());
            String unit = "";
            Double rate = jsonObject.getDouble(MultiUnitConstant.RATE) == null ? 1D : jsonObject.getDouble(MultiUnitConstant.RATE);
            jsonObject.put(BusinessConstant.PRODUCT_SUB_ID,0);
            if (productMap.containsKey(productId)){
                Double num = jsonObject.getDouble(PurchaseProductEnum.NUM.getAttr());
                jsonObject.put(PurchaseProductEnum.PURCHASE_PRICE.getAttr(), Arith.mul(rate, productMap.get(productId)));
                money = Arith.mul(num, jsonObject.getDouble(PurchaseProductEnum.PURCHASE_PRICE.getAttr()));
                jsonObject.put(PurchaseProductEnum.SUBTOTAL.getAttr(),money);
                jsonObject.put(PurchaseProductEnum.UNIT.getAttr(), formDataValidateProductHelp.formatUnit(corpid, StringUtil.isEmpty(unit) ? productUnitMap.get(productId) : unit));
            }else {
                iterator.remove();
            }
            totalMoney += money;
        }
        return totalMoney;
    }

    /**
     * 将Excel数据格式化成表单保存需要的JSON格式的数据
     *
     * @param importFormDataDTO 导入入参
     * @param titlePojoList     标题
     * @param rowGroupPojo      一个表单对应的一组Excel填写的数据
     * @param fieldAttrList     解释
     * @return FormDataAddDTO
     * @throws XbbException XbbException
     * @author youli.chen
     * @date 2019/4/29 14:16
     * @since V1.0
     */
    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        String corpid = importFormDataDTO.getCorpid();
        // data 数据
        JSONObject dataJson = new JSONObject();
        dataJson.put(PurchaseEnum.PRODUCT.getAttr(), new JSONArray());

        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);
        for (FieldAttrEntityForImport item : fieldAttrList) {
            String attr = item.getAttr();
            Integer fieldType = item.getFieldType();
            String attrName = item.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);


            if (Objects.equals(attr, PurchaseEnum.SUPPLIER_ID.getAttr())) {
                importHelper.formatSuppplier2SupplierId(cellValue.toString(), dataJson, item);
            } else if (Objects.equals(attr, PurchaseEnum.PRODUCT.getAttr())) {
                // 获取产品array
                importHelper.formatCommonProduct(titlePojoList, dataJson, rowValueList, item, XbbRefTypeEnum.PURCHASE.getCode(), corpid);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType())) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, item, dataJson);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                formDataAddDTO.setSerialNo(cellValue.toString());
            } else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(item.getFieldType())) {
                    importHelper.formatCommonField(dataJson, item, cellValue);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                    importHelper.formatLinkData(cellValue, item, dataJson);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                    importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, item, dataJson);
                } else {
                    dataJson.put(attr, cellValue);
                }
            }
//            if (Objects.equals(attr, PurchaseEnum.ADD_PAYPLAN.getAttr())) {
//                if (Objects.nonNull(item.getSubForm()) && Objects.nonNull(item.getSubForm().getItems())) {
//                    explainMap = ExplainUtil.getExplainMap(item.getSubForm().getItems().toJSONString(), null);
//                }
//            }
        }
//        JSONArray payPlanArr = dataJson.getJSONArray(PurchaseEnum.ADD_PAYPLAN.getAttr());
//        List<String> canCoverStatusList = Arrays.asList(PayPlanStatusEnum.RECEIVABLES.getCode(), PayPlanStatusEnum.UN_RECEIVABLES.getCode());
//        if (Objects.nonNull(payPlanArr) && !payPlanArr.isEmpty()) {
//            for (int i = 0; i < payPlanArr.size(); i++) {
//                JSONObject payPlanObj = payPlanArr.getJSONObject(i).getJSONObject(StringConstant.JSON_DATA);
//                if (!canCoverStatusList.contains(payPlanObj.getString(PayPlanEnum.STATUS.getAttr()))) {
//                    throw new XbbException(ErrorCodeEnum.API_ERROR_235020);
//                }
//                if (Objects.equals(payPlanObj.getString(PayPlanEnum.STATUS.getAttr()), PayPlanStatusEnum.RECEIVABLES.getCode())) {
//                    payPlanObj.put(PayPlanEnum.BELONGER.getAttr(), dataJson.get(PurchaseEnum.SIGNER_ID.getAttr()));
//                }
//                if (Objects.nonNull(payPlanObj.get(FieldTypeEnum.DEPARTMENTID.getAlias()))) {
//                    Long departmentId = departmentService.verifyDepartment(importFormDataDTO, explainMap, payPlanObj);
//                    payPlanArr.getJSONObject(i).put(FieldTypeEnum.DEPARTMENTID.getAlias(), departmentId);
//                    payPlanObj.put(FieldTypeEnum.DEPARTMENTID.getAlias(), new ReturnUserAndDepartmentPojo(departmentId));
//                }
//            }
//        }
//        dataJson.put(PurchaseEnum.ADD_PAYPLAN.getAttr(), payPlanArr);
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    /**
     * 格式化导出值
     *
     * @param paasFormDataESList 数据
     * @param formDataListDTO
     * @param fieldAttrList
     * @throws XbbException 异常
     */
    @Override
    public void formatExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList, Integer businessType) throws XbbException {
        FieldAttrEntityForImport payPlanField = null;
        FieldAttrEntityForImport productField = null;
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            if (Objects.equals(fieldAttrEntityForImport.getAttr(), PurchaseEnum.PRODUCT.getAttr())) {
                productField = fieldAttrEntityForImport;
            }
        }
        List<Long> businessIdIn = new ArrayList<>();
        paasFormDataESList.forEach(paasFormDataEntityExt -> businessIdIn.add(paasFormDataEntityExt.getId()));
        Set<Long> productIdIn = new HashSet<>();
        List<PurchaseProductEntity> purchaseProductByPurchaseIdIn = purchaseProductModel.getPurchaseProductByPurchaseIdIn(formDataListDTO.getCorpid(), businessIdIn);
        purchaseProductByPurchaseIdIn.forEach(item -> productIdIn.add(item.getProductId()));
//        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        param.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
//        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        String keyword = StringConstant.POINT + StringConstant.KEY_WORD;
        BoolQueryBuilder boolQueryBuilder = boolQuery();
//        boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + keyword, formDataListDTO.getCorpid()));
//        boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
//        String esData = StringConstant.JSON_DATA + StringConstant.POINT;
//        boolQueryBuilder.filter(termsQuery(esData + PayPlanEnum.LINK_PURCHASE.getAttr() + keyword, businessIdIn));
        //List<String> fieldList = new ArrayList<>();
        //fieldList.add(StringConstant.DATA_ID);
        //fieldList.add(StringConstant.JSON_DATA);
//        List<PaasFormDataEntityExt> purchaseLinkPayPlanList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAY_PLAN, boolQueryBuilder, PaasFormDataEntityExt.class, null);
        boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + keyword, formDataListDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), productIdIn));
        List<PaasFormDataEntityExt> productDataEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntityExt.class, null);
        Map<Long, PaasFormDataEntityExt> orginProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        productDataEntityList.forEach(item -> orginProductMap.put(item.getDataId(), item));
        Map<Long, List<PurchaseProductEntity>> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<PaasFormDataEntityExt>> payPlanMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        purchaseProductByPurchaseIdIn.forEach(purchaseProductEntity -> {
            List<PurchaseProductEntity> productEntityList = new ArrayList<>();
            if (productMap.containsKey(purchaseProductEntity.getPurchaseSheetId())) {
                productEntityList.addAll(productMap.get(purchaseProductEntity.getPurchaseSheetId()));
            }
            productEntityList.add(purchaseProductEntity);
            productMap.put(purchaseProductEntity.getPurchaseSheetId(), productEntityList);
        });
//        purchaseLinkPayPlanList.forEach(payPlan -> {
//            List<PaasFormDataEntityExt> payPlanEntityList = new ArrayList<>();
//            Long linkPurchaseId = payPlan.getData().getLong(PayPlanEnum.LINK_PURCHASE.getAttr());
//            if (payPlanMap.containsKey(linkPurchaseId)) {
//                payPlanEntityList.addAll(payPlanMap.get(linkPurchaseId));
//            }
//            payPlanEntityList.add(payPlan);
//            payPlanMap.put(linkPurchaseId, payPlanEntityList);
//        });
        if (Objects.nonNull(productField)){
            SubFormPoJo subFormPoJo = productField.getSubForm();
            List<FieldAttrEntityForImport> subFieldAttrList = JSON.parseArray(JSON.toJSONString(subFormPoJo.getItems()), FieldAttrEntityForImport.class);
//        int accuracy = 2;
//        boolean priceVisible = false;
//        boolean priceOpen = false;
            for (FieldAttrEntityForImport item : subFieldAttrList) {
                if (Objects.equals(item.getAttr(), PRODUCT_PRICE.getAttr())) {
//                accuracy = item.getAccuracy() == null ? 2 : item.getAccuracy();
                    //costVisible = Objects.equals(item.getVisible(), 1);
                    HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
                    BeanUtil.copyProperties(formDataListDTO, handlerExplainDTO, false);
//                priceVisible = !ExplainUtil.isFieldNeedHide(item, handlerExplainDTO);
//                priceOpen = Objects.equals(item.getIsOpen(), 1);
                }
            }
        }
        Map<String, MultiUnitItemPoJo> groupBaseUnitStringMap = relativeProductHelp.getGroupBaseUnitStringMap(formDataListDTO.getCorpid());

        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            JSONObject data = paasFormDataEntityExt.getData();
            List<PurchaseProductEntity> singlePurchaseProductEntityList = productMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>());
            List<PaasFormDataEntityExt> singlePurchasePayPlanList = payPlanMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>());
            for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
                if (Objects.equals(fieldAttrEntityForImport.getAttr(), PurchaseEnum.PRODUCT.getAttr())) {
                    JSONArray productArray = new JSONArray();
                    for (PurchaseProductEntity entity : singlePurchaseProductEntityList) {
                        if (orginProductMap.containsKey(entity.getProductId())) {
                            JSONObject productItemObj = new JSONObject();
                            if (Objects.nonNull(entity.getData())) {
                                productItemObj.putAll(entity.getData());
                            }
                            if (Objects.nonNull(entity.getPriceData()) && !Objects.equals(BasicConstant.ZERO, entity.getPriceData().size())){
                                entity.getData().putAll(entity.getPriceData());
                            }
                            JSONObject productData = orginProductMap.get(entity.getProductId()).getData();
                            productItemObj.put(SelectProductEnum.PRODUCT_NAME.getAttr(), productData.get(ProductEnum.NAME.getAttr()));
                            productItemObj.put(SelectProductEnum.PRODUCT_NO.getAttr(), orginProductMap.get(entity.getProductId()).getSerialNo());
                            String productSpecification = Objects.equals(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()), "{}") ? "" : productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                            productItemObj.put(SelectProductEnum.SPECIFICATION.getAttr(), productSpecification);
                            productItemObj.put(PurchaseProductEnum.NUM.getAttr(), entity.getProductNum());
                            productItemObj.put(SelectProductEnum.UNIT.getAttr(), productData.get(ProductEnum.UNIT.getAttr()));
                            productItemObj.put(SelectProductEnum.BARCODE.getAttr(),productData.get(ProductEnum.BARCODE.getAttr()));
                            productItemObj.put(ProductEnum.ENABLE_MULTI_UNIT.getAttr(), productData.getIntValue(ProductEnum.ENABLE_MULTI_UNIT.getAttr()));
                            // TODO 精度
                            if (Objects.isNull(entity.getPriceData()) || Objects.equals(entity.getPriceData().size(), BasicConstant.ZERO)) {
                                productItemObj.put(PurchaseProductEnum.PURCHASE_PRICE.getAttr(), entity.getProductPrice());
                                productItemObj.put(PurchaseProductEnum.SUBTOTAL.getAttr(), Arith.mul(entity.getProductPrice(), entity.getProductNum()));
                            }else {
                                productItemObj.put(PurchaseProductEnum.PURCHASE_PRICE.getAttr(), entity.getData().get(PurchaseProductEnum.PURCHASE_PRICE.getAttr()));
                                productItemObj.put(PurchaseProductEnum.SUBTOTAL.getAttr(), Arith.mul(entity.getData().getDouble(PurchaseProductEnum.PURCHASE_PRICE.getAttr()), entity.getBusinessNum()));
                            }
                            productItemObj.put(PurchaseProductEnum.MEMO.getAttr(), entity.getMemo());
                            productItemObj.put(PurchaseProductEnum.INSTOCK_NUM.getAttr(), entity.getInstockNum());
                            Double num = Arith.sub(entity.getProductNum(), entity.getInstockNum());
                            Double waitInstocknum = num >=0 ? num : 0D;
                            productItemObj.put(PurchaseProductEnum.WAIT_INSTOCK_NUM.getAttr(), waitInstocknum);
                            productItemObj.put(PurchaseProductEnum.RETURN_NUM.getAttr(), entity.getOutstockNum());
                            //基本单位时直接塞入productUnit
                            if (Objects.isNull(entity.getBusinessUnit())){
                                if (Objects.equals(productItemObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                                    productItemObj.put(ProductEnum.UNIT.getAttr(), groupBaseUnitStringMap.getOrDefault(productItemObj.getString(ProductEnum.UNIT.getAttr()), new MultiUnitItemPoJo()).getBaseValue());
                                    entity.setProductUnit(productItemObj.getString(ProductEnum.UNIT.getAttr()));
                                }
                                productItemObj.put(SelectProductEnum.NUM.getAttr(), entity.getProductNum());
                            }else {
                                productItemObj.put(ProductEnum.UNIT.getAttr(), entity.getBusinessUnit());
                                productItemObj.put(SelectProductEnum.NUM.getAttr(), entity.getBusinessNum());
                                productItemObj.put(PurchaseProductEnum.INSTOCK_NUM.getAttr(), Arith.div(entity.getInstockNum(), entity.getRate()));
                                productItemObj.put(PurchaseProductEnum.RETURN_NUM.getAttr(), Arith.div(entity.getOutstockNum(), entity.getRate()));
                                num = Arith.sub(entity.getBusinessNum(), Arith.div(entity.getInstockNum(), entity.getRate()));
                                waitInstocknum = num >=0 ? num : 0D;
                                productItemObj.put(PurchaseProductEnum.WAIT_INSTOCK_NUM.getAttr(), waitInstocknum);
                            }

                            if(Objects.equals(productItemObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                                productItemObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), entity.getProductUnit());
                                productItemObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(),  entity.getProductNum());
                            }else {
                                productItemObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), "");
                                productItemObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(), "");
                            }
                            productArray.add(productItemObj);
                        }
                    }
                    data.put(PurchaseEnum.PRODUCT.getAttr(), productArray);
                }
//                if (Objects.equals(fieldAttrEntityForImport.getAttr(), PurchaseEnum.ADD_PAYPLAN.getAttr())) {
//                    JSONArray payPlanArray = new JSONArray();
//                    Map<String, Object> userMap = formDataListDTO.getUserMap();
//                    Map<String, Object> deptMap = formDataListDTO.getDeptMap();
//                    List<FieldAttrEntity> fieldAttrEntityList = payPlanField.getSubForm().getItems().toJavaList(FieldAttrEntity.class);
//                    List<FieldAttrEntityForImport> fieldAttrEntityForImportList = fieldAttrEntityForImport.getSubForm().getItems().toJavaList(FieldAttrEntityForImport.class);
//                    for (PaasFormDataEntityExt payPlanEntity : singlePurchasePayPlanList) {
//                        JSONObject payPlanItemObj = payPlanEntity.getData();
//                        importHelper.formatCommonData4Export(userMap, deptMap, payPlanEntity, payPlanItemObj, fieldAttrEntityList, null, null, businessType);
//                        importHelper.formatDropDown4Export(fieldAttrEntityForImportList, payPlanItemObj);
//                        payPlanArray.add(payPlanItemObj);
//                    }
//                    data.put(PurchaseEnum.ADD_PAYPLAN.getAttr(), payPlanArray);
//                }
            }
        }
    }

    /**
     * 待入库合同维度导出
     *
     * @param paasFormDataESList 数据
     * @param formDataListDTO
     * @throws XbbException 异常
     */
    @Override
    public void formatWaitInstockPurchaseExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO) throws XbbException {
        //封装待入库产品数据
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList){
            JSONObject data = paasFormDataEntityExt.getData();
            JSONArray productJSONArray = new JSONArray();
            List<WaitOutstockProductPojo> waitOutstockProductPojoList = (List<WaitOutstockProductPojo>) data.getJSONObject("option_8").get("tableData");
            for (WaitOutstockProductPojo waitOutstockProductPojo : waitOutstockProductPojoList){
                JSONObject waitInstockProduct = new JSONObject();
                waitInstockProduct.put(WaitInstockEnum.PRODUCT_NAME.getAttr(),waitOutstockProductPojo.getProductName());
                waitInstockProduct.put(WaitInstockEnum.PRODUCT_NO.getAttr(),waitOutstockProductPojo.getProductNo());
                waitInstockProduct.put(WaitInstockEnum.SPECIFICATION.getAttr(),waitOutstockProductPojo.getSpecification());
                waitInstockProduct.put(WaitInstockEnum.UNIT.getAttr(),waitOutstockProductPojo.getUnit());
                waitInstockProduct.put(WaitInstockEnum.STOCK.getAttr(),waitOutstockProductPojo.getProductNum());
                waitInstockProduct.put(WaitInstockEnum.MEMO.getAttr(),waitOutstockProductPojo.getMemo());
                productJSONArray.add(waitInstockProduct);
            }
            data.put("array_1",productJSONArray);
            String name = data.getJSONArray(WaitInstockEnum.SUPPLIER_ID.getAttr()).getJSONObject(0).getString("name");
            data.put(WaitInstockEnum.SUPPLIER_ID.getAttr(),name);
            String addTime = DateTimeUtil.getStringEpochSecond(data.getLong(PurchaseEnum.ADD_TIME.getAttr()), DateTimeUtil.SDF);
            String updateTime = DateTimeUtil.getStringEpochSecond(data.getLong(PurchaseEnum.UPDATE_TIME.getAttr()), DateTimeUtil.SDF);
            String signTime = DateTimeUtil.getStringEpochSecond(data.getLong(WaitInstockEnum.SIGN_TIME.getAttr()), DateTimeUtil.SDFDate);
            String arriveTime = DateTimeUtil.getStringEpochSecond(data.getLong(WaitInstockEnum.ESTIMATE_ARRIVE_TIME.getAttr()), DateTimeUtil.SDFDate);
            data.put(PurchaseEnum.ADD_TIME.getAttr(),addTime);
            data.put(PurchaseEnum.UPDATE_TIME.getAttr(),updateTime);
            data.put(PurchaseEnum.SIGN_TIME.getAttr(),signTime);
            data.put(PurchaseEnum.ESTIMATE_ARRIVE_TIME.getAttr(),arriveTime);
            data.remove("option_8");
        }
    }

    @Override
    public BaseVO changeStatus(ChangeStatusDTO changeStatusDTO) throws XbbException {
        // TODO 采购合同编辑权限校验
        Long dataId = changeStatusDTO.getDataId();
        Integer businessType = changeStatusDTO.getBusinessType();
        String corpid = changeStatusDTO.getCorpid();
        PaasFormDataEntityExt paasFormDataEntityExt = saasGetHelp.getFormData(dataId, corpid, businessType);
        if (paasFormDataEntityExt == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        JSONObject bomData = paasFormDataEntityExt.getData();
        String status = changeStatusDTO.getType();
        String oldStatus = FastJsonHelper.getStringOrDefaultFromFormData(bomData, PurchaseEnum.STATUS.getAttr(), "");
        if (Objects.equals(oldStatus, status)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, ErrorMessageConstant.STATUS_NOT_MODIFIED);
        } else {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(PurchaseEnum.STATUS.getAttr(), status);
            UpdateDataEntity updateData = ExplainUtil.getUpdateData(dataId, jsonObject, corpid);
            purchaseModel.updateBatch(Collections.singletonList(updateData), corpid);
            //  TODO 消息
        }
        return new BaseVO();
    }

    @Override
    public void dataConsistencyUpdateSupplier(String corpid, Long dataId, String name) throws XbbException {
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0))
                    .filter(termQuery(PurchaseEnum.getEsAttr4Keyword(PurchaseEnum.SUPPLIER_ID), dataId));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PURCHASE, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<PurchaseEntityExt> purchaseEntityExtList = purchaseModel.findEntitys(param);

            if (Objects.nonNull(purchaseEntityExtList) && !purchaseEntityExtList.isEmpty()) {
                List<PurchaseUpdateDTO> purchaseUpdateDTOList = new ArrayList<>();
                for (PurchaseEntityExt entityExt : purchaseEntityExtList) {
                    PurchaseUpdateDTO purchaseUpdateDTO = new PurchaseUpdateDTO();
                    purchaseUpdateDTO.setId(entityExt.getId());
                    JSONObject data = new JSONObject();
                    data.put(PurchaseEnum.SUPPLIER_ID_LINKED_TEXT.getAttr(), name);
                    purchaseUpdateDTO.setData(data);
                    purchaseUpdateDTOList.add(purchaseUpdateDTO);
                }
                PurchaseUpdateBatchDTO purchaseUpdateBatchDTO = new PurchaseUpdateBatchDTO();
                purchaseUpdateBatchDTO.setCorpid(corpid);
                purchaseUpdateBatchDTO.setPurchaseList(purchaseUpdateDTOList);
                updateBatch(purchaseUpdateBatchDTO);
            }

        } catch (Exception e) {
            LOG.error("purchaseServiceImpl.dataConsistencyUpdateSupplier 出错， corpid=" + corpid + "  contactId=" + dataId + "  contactName=" + name, e);
        }
    }

    private void setSupplierDefaultValue(String corpid, List<Long> productIds, FieldAttrEntity supplierField, Long formId) throws XbbException{
        boolean strongAssociation = false;
        FormConfigEntity formConfigEntity = formConfigModel.getEntityByFormId(corpid, formId, FormConfigEnum.PURCHASE_PRODUCT_MUST_BELONG_SUPPLIER.getConfig());
        if (Objects.isNull(formConfigEntity)){
            strongAssociation = Objects.equals(FormConfigEnum.PURCHASE_PRODUCT_MUST_BELONG_SUPPLIER.getConfigValue(),BasicConstant.IS_USE.toString());
        } else if (Objects.equals(formConfigEntity.getConfigValue(), BasicConstant.IS_USE.toString())) {
            strongAssociation = true;
        }
//        List<SupplierProductEntity> supplierProductEntityList = supplierProductModel.findCommonSupplier(corpid,productIds);
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid",corpid);
        param.put("del",0);
        param.put("productIdIn",productIds);
        List<SupplierProductEntity> supplierProductEntityList = supplierProductModel.findEntitys(param);
        Map<Long, List<Long>> productSupplierListMap = new HashMap<>(16);
        for (Long productId : productIds) {
            List<Long> supplierIds = new ArrayList<>();
            for (SupplierProductEntity supplierProductEntity : supplierProductEntityList) {
                if (Objects.equals(productId, supplierProductEntity.getProductId())) {
                    supplierIds.add(supplierProductEntity.getSupplierId());
                }
            }
            productSupplierListMap.put(productId, supplierIds);
        }

        List<List<Long>> allSupplierValues = new ArrayList<>(productSupplierListMap.values());
        List<Long> commonSupplierList = new ArrayList<>();
        if (allSupplierValues.size() > 0) {
            Object linkFormValue = supplierField.getDefaultAttr().getLinkFormValue();
            if (Objects.nonNull(linkFormValue)){
                JSONArray jsonArray = JSONArray.parseArray(linkFormValue.toString());
                if (CollectionsUtil.isNotEmpty(jsonArray)){
                    JSONObject jsonObject = jsonArray.getJSONObject(0);
                    if (Objects.nonNull(jsonObject)){
                        Long suppid = jsonObject.getLong("id");
                        commonSupplierList.add(suppid);
                    }
                }
            }
            // 防止没取到供应商ID 做个兜底操作
            if (CollectionsUtil.isEmpty(commonSupplierList)){
                commonSupplierList = allSupplierValues.get(0);
            }
            for (int i=1; i<allSupplierValues.size(); i++) {
                List<Long> tempSupplierList = allSupplierValues.get(i);
                commonSupplierList.retainAll(tempSupplierList);
            }
        }

        if (commonSupplierList.isEmpty() && strongAssociation){
            throw new XbbException(PurchaseErrorCodeEnum.API_ERROR_225022);
        }
        if (!commonSupplierList.isEmpty()){
            Long supplierId = commonSupplierList.get(BasicConstant.ZERO);
            SupplierEntityExt supplierEntityExt = supplierModel.getByKey(supplierId, corpid);
            String supplierName = FastJsonHelper.getStringOrDefaultFromFormData(supplierEntityExt.getData(), SupplierEnum.SUPPLIER_NAME.getAttr(), "");
            supplierField.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(supplierId, supplierName,corpid, XbbRefTypeEnum.SUPPLIER, XbbRefTypeEnum.PREPAY_BALANCE));
            if (strongAssociation) {
                SaasParticularAttributePoJo saasParticularAttributePoJo = supplierField.getSaasParticularAttributePoJo() == null ? new SaasParticularAttributePoJo() : supplierField.getSaasParticularAttributePoJo();
//                saasParticularAttributePoJo.setIdIn(commonSupplierIds);
                supplierField.setSaasParticularAttributePoJo(saasParticularAttributePoJo);
            }
        }
    }

    /**
     * 根据采购合同id获取采购合同产品的采购价
     *
     * @param corpid 获取采购订单关联产品的条件
     * @param purchaseId 获取采购订单关联产品的条件
     * @return productCostMap   产品id和成本价之间的key-value关系
     * @since v3.22
     * @author lcx
     */
    @Override
    public Map<Long, Double> getReturnedProdCostMap(String corpid, Long purchaseId) {
        List<PurchaseProductEntity> purchaseProductEntities = purchaseProductModel.getProductsByPurchaseId(corpid, purchaseId);
        HashMap<Long, PurchaseProductEntity> purchaseProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, Double> productCostMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 获取关联产品的采购价（关联产品是可以重复的所以这里相同id的产品的采购价要平均算一下）作为成本价
        if (purchaseProductEntities != null && purchaseProductEntities.size() > 0) {
            for (PurchaseProductEntity purchaseProductEntity : purchaseProductEntities) {
                Long productId = purchaseProductEntity.getProductId();
                if (purchaseProductMap.containsKey(productId)) {
                    PurchaseProductEntity preProductEntity = purchaseProductMap.get(productId);
                    Double preProductPrice = preProductEntity.getProductPrice();
                    Double preProductNum = preProductEntity.getProductNum();
                    Double nowProductPrice = purchaseProductEntity.getProductPrice();
                    Double nowProductNum = purchaseProductEntity.getProductNum();
                    double totalProductNum = Arith.add(preProductNum, nowProductNum);
                    double nowProductAvgCost = 0D;
                    if (totalProductNum > 0) {
                        nowProductAvgCost = Arith.div(Arith.add(Arith.mul(preProductPrice, preProductNum), Arith.mul(nowProductPrice, nowProductNum)),totalProductNum);
                    }
                    purchaseProductEntity.setProductNum(totalProductNum);
                    purchaseProductEntity.setProductPrice(nowProductAvgCost);
                    purchaseProductMap.put(productId, purchaseProductEntity);
                } else {
                    purchaseProductMap.put(productId, purchaseProductEntity);
                }
            }
        }
        // 构建产品id和成本价之间的关系productCostMap
        if (purchaseProductMap.size() > 0) {
            for (Map.Entry<Long, PurchaseProductEntity> map : purchaseProductMap.entrySet()) {
                productCostMap.put(map.getKey(), map.getValue().getProductPrice());
            }
        }
        return productCostMap;
    }

    @Override
    public boolean judgePurchaseAllInBound(Long instockId, Long purchaseId, String corpid, List<ProductSavePojo> productSavePojoList) throws XbbException {
        return purchaseHelp.judgePurchaseAllInBound(instockId, purchaseId, corpid,productSavePojoList);
    }

    @Override
    public PagingProductVO getPagingProduct(PagingProductDTO pagingProductDTO) throws XbbException {
        PagingProductVO pagingProductVO = new PagingProductVO();
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, pagingProductDTO.getCorpid());
        modelMap.put(ParameterConstant.PURCHASE_SHEET_ID, pagingProductDTO.getDataId());
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put(ParameterConstant.PAGE,  pagingProductDTO.getPage());
        modelMap.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
        PageHelper pageHelper = PageHelperUtil.getPageHelper(modelMap, purchaseProductModel, pagingProductDTO.getPageSize());
        List<PurchaseProductEntity> purchaseProductEntityList = (List<PurchaseProductEntity>) PageHelperUtil.getEntityList(modelMap, pageHelper, purchaseProductModel);
        if (pagingProductDTO.getUpdateDataTypeEnum().isDetail()) {
            DetailProductVO detailProductVO = formatProduct4DetailShow(purchaseProductEntityList, pagingProductDTO);
            pagingProductVO.setProductDataArr(detailProductVO.getProductDataArr());
        }
        pagingProductVO.setPageHelper(pageHelper);
        return pagingProductVO;
    }

    public DetailProductVO formatProduct4DetailShow(List<PurchaseProductEntity> purchaseProductEntityList, PagingProductDTO pagingProductDTO) throws XbbException{
        DetailProductVO detailProductVO = new DetailProductVO();
        Set<Long> productIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PurchaseProductEntity purchaseProductEntity : purchaseProductEntityList) {
            productIds.add(purchaseProductEntity.getProductId());
        }
        String corpid = pagingProductDTO.getCorpid();
        JSONArray productArray = new JSONArray();
        PaasFormExplainEntity productExplains = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
        if (Objects.isNull(productExplains)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> productExplainMap = ExplainUtil.getExplainMap(productExplains.getExplains(), null);
        for (PurchaseProductEntity purchaseProductEntity : purchaseProductEntityList) {
            JSONObject json = new JSONObject();
            if (Objects.nonNull(purchaseProductEntity.getData())) {
                json = purchaseProductEntity.getData();
            }
            if (Objects.nonNull(purchaseProductEntity.getBusinessUnit())) {
                purchaseProductEntity.setProductNum(Arith.div(purchaseProductEntity.getProductNum(), purchaseProductEntity.getRate()));
                purchaseProductEntity.setProductUnit(purchaseProductEntity.getBusinessUnit().toString());
                purchaseProductEntity.setInstockNum(Arith.div(purchaseProductEntity.getInstockNum(), purchaseProductEntity.getRate()));
                purchaseProductEntity.setOutstockNum(Arith.div(purchaseProductEntity.getOutstockNum(), purchaseProductEntity.getRate()));
                if (Objects.nonNull(purchaseProductEntity.getPriceData())) {
                    purchaseProductEntity.setProductPrice(purchaseProductEntity.getPriceData().getDouble(SelectProductEnum.PRICE.getAttr()));
                }
            }
            for (PurchaseProductEnum purchaseProductEnum : PurchaseProductEnum.values()) {
                if (!UpdateDataTypeEnum.DETAIL.formatShow(purchaseProductEnum.getShowType())) {
                    continue;
                }
                String attr = purchaseProductEnum.getAttr();
                switch (purchaseProductEnum) {
                    case PRODUCT:
                        json.put(attr, purchaseProductEntity.getProductId());
                        break;
                    case PURCHASE_PRICE:
                        json.put(attr, purchaseProductEntity.getProductPrice());
                        break;
                    case NUM:
                        json.put(attr, purchaseProductEntity.getProductNum());
                        break;
                    case SUBTOTAL:
                        json.put(attr, Arith.mul(purchaseProductEntity.getProductNum(), purchaseProductEntity.getProductPrice()));
                        break;
                    case MEMO:
                        json.put(attr, purchaseProductEntity.getMemo());
                        break;
                    case UNIT:
                        json.put(attr, purchaseProductEntity.getProductUnit());
                        break;
                    case INSTOCK_NUM:
                        json.put(attr,purchaseProductEntity.getInstockNum());
                        break;
                    case WAIT_INSTOCK_NUM:
                        Double num = Arith.sub(purchaseProductEntity.getProductNum(), purchaseProductEntity.getInstockNum());
                        Double waitInstockNum = num >= 0 ? num :0D;
                        json.put(attr, waitInstockNum);
                        break;
                    case RETURN_NUM:
                        json.put(attr,purchaseProductEntity.getOutstockNum());
                        break;
                    case RECEIVE_STATUS:
                        if (purchaseProductEntity.getInstockNum() > 0) {
                            if (Double.compare(purchaseProductEntity.getProductNum(), purchaseProductEntity.getInstockNum()) <= 0) {
                                json.put(attr, I18nMessageUtil.getMessage(I18nStringConstant.STOCK_IN_ALL));
                            } else {
                                json.put(attr, I18nMessageUtil.getMessage(I18nStringConstant.PARTIAL_WAREHOUSING));
                            }
                        } else {
                            json.put(attr, InOutStockStatusEnum.UN_INSTOCK.getName());
                        }
                        break;
                    default:
                        break;
                }
            }
            json.put(BusinessConstant.PRODUCT_SUB_ID, purchaseProductEntity.getId());
            productArray.add(json);
        }
        detailProductVO.setProductDataArr(productArray);
        return detailProductVO;
    }

    @Override
    public void formatProduct4Show2(Long dataId, String corpid, JSONObject data, UpdateDataTypeEnum updateDataTypeEnum) throws XbbException {
       purchaseModel.formatProduct4Show2(dataId, corpid, data, updateDataTypeEnum);
    }

    @Override
    public JSONObject formatSingleProduct(PurchaseProductEntity purchaseProductEntity) {
        return purchaseModel.formatSingleProduct(purchaseProductEntity);
    }

    @Override
    public void updateBatchByBusinessRule(PurchaseUpdateByBusinessRuleDTO purchaseUpdateByBusinessRuleDTO) throws XbbException {
        try {
            String corpid = purchaseUpdateByBusinessRuleDTO.getCorpid();
            List<PaasFormDataEntityExt> formDataList = purchaseUpdateByBusinessRuleDTO.getFormDataList();
            List<UpdateDataEntity> updateList = ExplainUtil.getUpdateValueByBusinessRule(formDataList, corpid, purchaseUpdateByBusinessRuleDTO.getOperations());

            if (!updateList.isEmpty()) {
                purchaseModel.updateBatch(updateList, corpid);
                RuleBusinessLogDTO businessLogDTO = new RuleBusinessLogDTO();
                BeanUtil.copyProperties(purchaseUpdateByBusinessRuleDTO, businessLogDTO);
                businessLogDTO.setFormDataList(formDataList);
                ruleBusinessLogger.writeLog(businessLogDTO, updateList);
            }
        } catch (Exception e) {
            LOG.error("purchaseService.updateFormDataByBusinessRule根据业务规则更新数据出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 更新收款比例
     *
     * @param corpid
     * @param sheetAmount
     * @param purchaseId
     * @param linkContractEntity
     * @throws XbbException
     */
    @Override
    public void updateProfit(String corpid, Double sheetAmount, Long purchaseId, PaasFormDataEntity linkContractEntity) throws XbbException {
        PaasFormDataEntity purchase;
        if ( Objects.nonNull(linkContractEntity) ) {
            purchase = linkContractEntity;
        } else {
            purchase = purchaseModel.getByKey(purchaseId, corpid);
        }

        if ( Objects.isNull(purchase) ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        Double finishMoney = getDoubleOrDefaultFromFormData(purchase.getData(), PurchaseEnum.FINISH_AMOUNT.getAttr(), 0D);
        Double amount = getDoubleOrDefaultFromFormData(purchase.getData(), PurchaseEnum.TOTAL_MONEY.getAttr(), 0D);
        Double badAmount = getDoubleOrDefaultFromFormData(purchase.getData(), PurchaseEnum.BAD_AMOUNT.getAttr(), 0D);
        JSONObject jsonObject = new JSONObject();
        Double newFinishMoney = Arith.add(finishMoney, sheetAmount);
        Double newUnFinishMoney = Arith.sub(Arith.sub(amount, Arith.add(finishMoney, sheetAmount)), badAmount);
        jsonObject.put(PurchaseEnum.FINISH_AMOUNT.getAttr(), newFinishMoney);
        jsonObject.put(PurchaseEnum.UN_FINISH_AMOUNT.getAttr(), newUnFinishMoney);
        if ( Double.compare(amount, BasicConstant.ZERO) == BasicConstant.ZERO ) {
            jsonObject.put(PurchaseEnum.RECEINE_PERCENT.getAttr(), BasicConstant.ZERO);
        } else {
            jsonObject.put(PurchaseEnum.RECEINE_PERCENT.getAttr(), Arith.round(Arith.div(newFinishMoney, amount), 4));
        }
        UpdateDataEntity updateData = ExplainUtil.getUpdateData(purchaseId, jsonObject, corpid);
        purchaseModel.updateBatch(Collections.singletonList(updateData), corpid);
    }

    @Override
    public List<UpdateDataEntity> handleContract(SheetTypeEnum sheetTypeEnum, String corpid, Map<Long, Double> contractIdToAmount, Set<Long> contractIds) throws XbbException {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("idIn", contractIds);
        List<PurchaseEntityExt> contracts = purchaseModel.findEntitys(param);
        if (Objects.isNull(contracts)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        boolean isRedFlag = SheetTypeEnum.isRed(sheetTypeEnum);
        boolean isBadFlag = SheetTypeEnum.isBad(sheetTypeEnum);
        List<UpdateDataEntity> updateList = new ArrayList<>();
        for (PurchaseEntityExt contractEntityExt : contracts) {
            String name = contractEntityExt.getSerialNo();
            if (Objects.equals(contractEntityExt.getDel(), DelEnum.DELETE.getDel())) {
                throw new XbbException(PaymentErrorCodeEnum.API_ERROR_208032, PaymentErrorCodeEnum.API_ERROR_208032.getMsg(), XbbRefTypeEnum.PURCHASE.getName(), name);
            }
            Long contractId = contractEntityExt.getId();
            Double value = contractIdToAmount.getOrDefault(contractId, 0D);
            if (value == 0) {
                continue;
            }
            Double tempAmount = value;
            if (isRedFlag) {
                //红冲的，先把红冲金额取正数，然后判断红冲金额是否小于已收
                tempAmount = Math.abs(value);
            }
            JSONObject data = contractEntityExt.getData();
            Double finishMoney = getDoubleOrDefaultFromFormData(data, PurchaseEnum.FINISH_AMOUNT.getAttr(), 0D);
            Double unAmount = getDoubleOrDefaultFromFormData(data, PurchaseEnum.UN_FINISH_AMOUNT.getAttr(), 0D);
            //校验填充的金额是否超过合同的已收/未收（根据是否红冲判断不同）
            if (isRedFlag) {
                //红冲，限制红冲金额tempAmount小于等于合同已收金额finishMoney
                if (Arith.sub(tempAmount , finishMoney) > ConfigConstant.amountAccuracy) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.DETAIL_BEYOND_AMOUNT_RED, XbbRefTypeEnum.PURCHASE.getName() + name);
                }
                //红冲的，把金额置为负数。用tempAmount计算金额是否合法
                value = Arith.mul(value, -1);
            } else if (Arith.sub(value , unAmount) > ConfigConstant.amountAccuracy) {
                //普通回款、坏账，限制回款金额小于等于合同未收金额
                String msg = I18nMessageUtil.getMessage(ErrorMessageConstant.DETAIL_BEYOND_AMOUNT_PAY);
                if (isBadFlag) {
                    msg = I18nMessageUtil.getMessage(ErrorMessageConstant.DETAIL_BEYOND_AMOUNT_BAD);
                }
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, String.format(msg, XbbRefTypeEnum.PURCHASE.getName(), name));
            }
            JSONObject updateData = new JSONObject();
            /*
             处理采购合同的已收未收
             （1）采购合同此次只增加实付金额、未付金额、收款比例
             （2）毛利、毛利率、成本这些是没有的（销售合同才会存在这种说法，采购合同是我们花钱去买东西，花出去的采购金额，都相当于企业付出的成本）- 凤娇
             */
            Double badAmount = getDoubleOrDefaultFromFormData(data, PurchaseEnum.BAD_AMOUNT.getAttr(), 0D);
            if (isBadFlag) {
                /*
                 坏账时：已收不变，合同总额不变，未收减少，坏账增加，收款比例不变（= 已收/总合同额）
                 */
                Double oldUnFinishMoney = getDoubleOrDefaultFromFormData(data, PurchaseEnum.UN_FINISH_AMOUNT.getAttr(), 0D);
                Double newUnFinishMoney = Arith.sub(oldUnFinishMoney, value);
                //坏账增加
                Double newBadAmount = Arith.add(badAmount, value);
                updateData.put(PurchaseEnum.UN_FINISH_AMOUNT.getAttr(), newUnFinishMoney);
                updateData.put(PurchaseEnum.BAD_AMOUNT.getAttr(), newBadAmount);
            } else {
                /*
                 普通、红冲回款时（红冲是负值，所以可以和普通回款一样处理方式）：已收增加，合同总额不变，未收减少，坏账不变-收款比例增加（= 已收/总合同额）
                 */
                Double amount = getDoubleOrDefaultFromFormData(data, PurchaseEnum.TOTAL_MONEY.getAttr(), 0D);
                //此处直接add没问题：红冲时value是负数
                //注：为防止与原逻辑不一致，此处来回加减的代码参照旧代码内对各种金额的处理
                Double newFinishMoney = Arith.add(finishMoney, value);
                //合同未收 = 合同金额 - 合同已收 - 合同坏账
                Double newUnFinishMoney = Arith.sub(amount, newFinishMoney);
                newUnFinishMoney = Arith.sub(newUnFinishMoney, badAmount);
                updateData.put(PurchaseEnum.FINISH_AMOUNT.getAttr(), newFinishMoney);
                updateData.put(PurchaseEnum.UN_FINISH_AMOUNT.getAttr(), newUnFinishMoney);
                saasUpdateHelp.handleAttrPercent(updateData, newFinishMoney, amount, PurchaseEnum.RECEINE_PERCENT.getAttr());
            }
            UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(contractId, updateData, corpid);
            updateList.add(updateDataEntity);
        }
        return updateList;
    }

    @Override
    public void updateRollback(Collection<Long> idIn, String corpid) throws XbbException {
        if (Objects.isNull(idIn) || idIn.isEmpty()) {
            return;
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put("idIn", idIn);
        List<PurchaseEntityExt> list = purchaseModel.findEntitysWithoutSub(param);
        if (Objects.nonNull(list)) {
            for (PurchaseEntityExt item : list) {
                PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
                BeanUtil.copyProperties(item, paasFormDataEntity);
                proEsHelper.reductionEsInUpdate(paasFormDataEntity, item.getId(), corpid, IndexTypeEnum.IDX_SAAS_PURCHASE);
            }
        }
    }

    @Override
    public List<UpdateDataEntity> updateContract4Del(String corpid, Set<String> errorTypeSet, Set<String> errorDataSet, Collection<Long> delIdList, SheetDeleteHandleRelateDTO sheetDeleteHandleRelateDTO) throws XbbException {
        Map<Long, Double> contractIdToAmount = sheetDeleteHandleRelateDTO.getContractIdToAmount();
        Map<Long, Double> contractIdToUnAmount = sheetDeleteHandleRelateDTO.getContractIdToUnAmount();
        Map<Long, Double> contractIdToBad = sheetDeleteHandleRelateDTO.getContractIdToBad();
        Set<Long> contractIds = sheetDeleteHandleRelateDTO.getContractIds();
        Map<Long, List<Long>> cidSheetIdListMap = sheetDeleteHandleRelateDTO.getCidSheetIdListMap();
        Map<Long, List<String>> cidSheetNoListMap = sheetDeleteHandleRelateDTO.getCidSheetNoListMap();
        List<String> delNoList = sheetDeleteHandleRelateDTO.getDelNoList();
        /*
         处理采购合同的已收未收等
         （1）采购合同此次只增加实付金额、未付金额、收款比例
         （2）毛利、毛利率、成本这些是没有的（销售合同才会存在这种说法，采购合同是我们花钱去买东西，花出去的采购金额，都相当于企业付出的成本）- 凤娇
         */
        PurchaseEnum enumAmount = PurchaseEnum.TOTAL_MONEY;
        PurchaseEnum enumFinishAmount = PurchaseEnum.FINISH_AMOUNT;
        PurchaseEnum enumUnFinishAmount = PurchaseEnum.UN_FINISH_AMOUNT;
        PurchaseEnum enumBadAmount = PurchaseEnum.BAD_AMOUNT;
        PurchaseEnum enumPayPercent = PurchaseEnum.RECEINE_PERCENT;
        List<String> fieldList = Arrays.asList(BasicConstant.ID, "del", PurchaseEnum.SHEET_NO.getAttr(), PurchaseEnum.getAttrConnectData(enumAmount), PurchaseEnum.getAttrConnectData(enumFinishAmount), PurchaseEnum.getAttrConnectData(enumUnFinishAmount), PurchaseEnum.getAttrConnectData(enumBadAmount), PurchaseEnum.getAttrConnectData(enumPayPercent));
        List<PaasFormDataEntityExt> contracts = formHelp.getFormListByIds4All(corpid, IndexTypeEnum.IDX_SAAS_PURCHASE, contractIds, fieldList);
        List<UpdateDataEntity> updateList = new ArrayList<>();
        if (Objects.isNull(contracts)) {
            //查不到关联数据，则不关联更新
            return updateList;
        }
        for (PaasFormDataEntityExt entityExt : contracts) {
            if (Objects.equals(entityExt.getDel(), DelEnum.DELETE.getDel())) {
                //采购合同已经删除，则跳过不处理
                continue;
            }
            Long contractId = entityExt.getId();
            JSONObject updateData = new JSONObject();
            JSONObject data = entityExt.getData();
            double finishAmount = commonHelp.handleAttrAmount(enumFinishAmount.getAttr(), contractIdToAmount, contractId, data, updateData);
            //已付小于0，则不能更新该采购合同、且不能删除该采购合同对应的付款单集合
            if(finishAmount < BasicConstant.ZERO_DOUBLE){
                //封装不能删除信息，并从delIdList、delNoList移除
                commonHelp.removeInfoAndAmountBack4DelError(true, I18nMessageUtil.getMessage(ErrorMessageConstant.NON_ZERO_PURCHASE_PAY_PLAN_AMOUNT), errorTypeSet, errorDataSet, cidSheetNoListMap, cidSheetIdListMap, delIdList, delNoList, contractId, sheetDeleteHandleRelateDTO);
                continue;
            }
            Double unAmount = commonHelp.handleAttrAmount(enumUnFinishAmount.getAttr(), contractIdToUnAmount, contractId, data, updateData);
            //未付小于0，则不能更新该采购合同、且不能删除该采购合同对应的付款单集合
            if(unAmount < BasicConstant.ZERO_DOUBLE){
                //封装不能删除信息，并从delIdList、delNoList移除
                commonHelp.removeInfoAndAmountBack4DelError(true, I18nMessageUtil.getMessage(ErrorMessageConstant.NON_ZERO_PURCHASE_PAY_PLAN_AMOUNT_UN), errorTypeSet, errorDataSet, cidSheetNoListMap, cidSheetIdListMap, delIdList, delNoList, contractId, sheetDeleteHandleRelateDTO);
                continue;
            }
            Double badAmount = commonHelp.handleAttrAmount(enumBadAmount.getAttr(), contractIdToBad, contractId, data, updateData);
            //坏账小于0，则不能更新该采购合同、且不能删除该采购合同对应的付款单集合
            if(badAmount < BasicConstant.ZERO_DOUBLE){
                //封装不能删除信息，并从delIdList、delNoList移除
                commonHelp.removeInfoAndAmountBack4DelError(true, I18nMessageUtil.getMessage(ErrorMessageConstant.NON_ZERO_PURCHASE_PAY_PLAN_AMOUNT_BAD), errorTypeSet, errorDataSet, cidSheetNoListMap, cidSheetIdListMap, delIdList, delNoList, contractId, sheetDeleteHandleRelateDTO);
                continue;
            }
            if (updateData.size() == 0) {
                //已付、未付、坏账金额都没变动
                continue;
            }
            Double amount = getDoubleOrDefaultFromFormData(data, enumAmount.getAttr(), 0D);
            saasUpdateHelp.handleAttrPercent(updateData, finishAmount, amount, enumPayPercent.getAttr());
            UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(contractId, updateData, corpid);
            updateList.add(updateDataEntity);
        }
        return updateList;
    }

    @Override
    public Map<Long,String> getPurchaseNameMap(List<Long> handoverIdSet, String corpid) throws XbbException {
        Map<Long,String> purchaseNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (handoverIdSet.isEmpty()){
            return purchaseNameMap;
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
        boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),handoverIdSet));
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_PURCHASE.getType()));
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(boolQueryBuilder);
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, handoverIdSet.size());
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_PURCHASE.getIndex());
        searchRequest.source(sourceBuilder);
        XbbAggregatedPage<PaasFormDataEntity> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest,searchRequest,PaasFormDataEntity.class);
        for (PaasFormDataEntity entity : esEntities.getContent()){
            purchaseNameMap.put(entity.getDataId(),entity.getData().getString(PurchaseEnum.PURCHASE_NAME.getAttr()));
        }
        return purchaseNameMap;
    }

    @Override
    public ChangeDocumentStatusSaveVO changeDocumentStatus(ChangeDocumentStatusSaveDTO changeDocumentStatusSaveDTO) throws XbbException{
        ChangeDocumentStatusSaveVO changeDocumentStatusSaveVO = new ChangeDocumentStatusSaveVO();
        try {
            Boolean isOpen = changeDocumentStatusSaveDTO.getIsOpen();
            String corpid = changeDocumentStatusSaveDTO.getCorpid();
            Long purchaseId = changeDocumentStatusSaveDTO.getDataId();
            Integer businessType = changeDocumentStatusSaveDTO.getBusinessType();
            PurchaseEntityExt purchaseEntityExt = purchaseModel.getByKey(purchaseId, corpid);
            if (Objects.isNull(purchaseEntityExt)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            JSONObject purchaseData = purchaseEntityExt.getData();
            List<PurchaseProductEntity> purchaseProductEntityList = purchaseProductModel.getProductsByPurchaseId(corpid, purchaseId);
            // 处理未出库数量
            Map<Long,Double> waitPurchaseNumMap = new HashMap<>();
            Set<Long> productIdSet = new HashSet<>();
            if (CollectionUtils.isNotEmpty(purchaseProductEntityList)){
                for (PurchaseProductEntity entity : purchaseProductEntityList) {
                    Long productId = entity.getProductId();
                    productIdSet.add(productId);
                    Double productNum = entity.getProductNum();
                    Double instockNum = entity.getInstockNum();
                    Double waitInstockNum = Arith.sub(productNum,instockNum);
                    if (waitPurchaseNumMap.containsKey(productId)){
                        waitPurchaseNumMap.put(productId,Arith.add(waitPurchaseNumMap.get(productId),waitInstockNum));
                    }else {
                        waitPurchaseNumMap.put(productId,waitInstockNum);
                    }
                }
            }
            // 查询出所有只能补货产品
            List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid, new ArrayList<>(productIdSet));

            //如果是开启采购合同
            if (isOpen) {
                Integer allInBound = purchaseData.getInteger(PurchaseEnum.ALL_INCOMING.getAttr());
                //如果全部入库则直接发货设置成全部入库
                if (Objects.equals(allInBound, AllInBoundEnum.ALL_IN.getCode())) {
                    purchaseData.put(PurchaseEnum.RECEIVE_STATUS.getAttr(),ReceiveStatusEnum.RECEIVED.getCode());
                }else {
                    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                    BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
                    boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                    boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE), InstockTypeEnum.PURCHASE_INSTOCK.getCode()));
                    boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID), purchaseId));
                    boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
                    boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_INSTOCK.getType()));
                    sourceBuilder.query(boolQueryBuilder);
                    PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, 1);
                    SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_INSTOCK.getIndex());
                    searchRequest.source(sourceBuilder);
                    XbbAggregatedPage<PaasFormDataEntityExt> entities = xbbElasticsearchRestTemplate.queryForPages(pageRequest,searchRequest, PaasFormDataEntityExt.class);

                    if (entities.getTotalElements() < 1){
                        purchaseData.put(PurchaseEnum.RECEIVE_STATUS.getAttr(), ReceiveStatusEnum.UNRECEIVED.getCode());
                    }else {
                        purchaseData.put(PurchaseEnum.RECEIVE_STATUS.getAttr(), ReceiveStatusEnum.PARTIAL.getCode());
                    }
                }
                // 更新只能补货未入库数量
                for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntityList) {
                    Long productId = smartReplenishmentEntity.getProductId();
                    Double waitNum = waitPurchaseNumMap.getOrDefault(productId, 0D);
                    smartReplenishmentEntity.setPendingInstockNum(Arith.add(smartReplenishmentEntity.getPendingInstockNum(),waitNum));
                }
            }else {
                purchaseData.put(PurchaseEnum.RECEIVE_STATUS.getAttr(), ReceiveStatusEnum.CLOSED.getCode());
                // 关闭则只能补货数量待入库数量要-掉改次待入库数量
                for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntityList) {
                    Long productId = smartReplenishmentEntity.getProductId();
                    Double waitNum = waitPurchaseNumMap.getOrDefault(productId, 0D);
                    smartReplenishmentEntity.setPendingInstockNum(Arith.sub(smartReplenishmentEntity.getPendingInstockNum(),waitNum));
                }
            }
            // 更新智能补货数据
            try {
                smartReplenishmentModel.updateBatch(smartReplenishmentEntityList, corpid);
            }catch (Exception e){
                LOG.error("PurchaseServiceImpl.changeDocumentStatus() 更新智能补货数据时出错", e);
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
            }
            purchaseModel.update(purchaseEntityExt);
            //添加关闭和开启采购合同的按钮
            String receiveStatus = FastJsonHelper.getStringOrDefaultFromFormData(purchaseData, PurchaseEnum.RECEIVE_STATUS.getAttr(), ReceiveStatusEnum.UNRECEIVED.getCode());
            //如果全部出库，则没有开启关闭按钮
            if (!Objects.equals(receiveStatus, ReceiveStatusEnum.RECEIVED.getCode())) {
                ButtonPojo buttonPojo = new ButtonPojo();
                if (Objects.equals(receiveStatus,ReceiveStatusEnum.CLOSED.getCode())&&changeDocumentStatusSaveDTO.getLoginUser().getPermSet().contains(EnableButtonEnum.PURCHASE_ENABLE.getPermission())) {
                    buttonPojo.setAttr("purchase");
                    buttonPojo.setValue(OperateTypeEnum.ENABLE.getName());
                    buttonPojo.setLinkBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
                    List<ButtonPojo> topRightButton = new ArrayList<>();
                    topRightButton.add(buttonPojo);
                    changeDocumentStatusSaveVO.setTopRightButton(topRightButton);
                }else if (!Objects.equals(receiveStatus,ReceiveStatusEnum.CLOSED.getCode())&&changeDocumentStatusSaveDTO.getLoginUser().getPermSet().contains(EnableButtonEnum.PURCHASE_UNABLE.getPermission())){
                    buttonPojo.setAttr("purchase");
                    buttonPojo.setValue(OperateTypeEnum.UNABLE.getName());
                    buttonPojo.setLinkBusinessType(XbbRefTypeEnum.PURCHASE.getCode());
                    List<ButtonPojo> topRightButton = new ArrayList<>();
                    topRightButton.add(buttonPojo);
                    changeDocumentStatusSaveVO.setTopRightButton(topRightButton);
                }
            }
            // 刷新页面saas关联新建工作流
            PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
            BeanUtil.copyProperties(purchaseEntityExt,paasFormDataEntityExt);
            if (Objects.equals(PlatFormEnum.DINGTALK.getValue(), changeDocumentStatusSaveDTO.getPlatform())) {
                // 设置移动端详情右上角操作
                FormDataGetVO formDataGetVO = new FormDataGetVO();
                mobileDetailService.handelMobileWorkFlow(changeDocumentStatusSaveDTO.getLoginUser(), businessType, formDataGetVO, paasFormDataEntityExt);
                changeDocumentStatusSaveVO.setTopPermissions(formDataGetVO.getTopPermissions());
            }else {
                List<WorkFlowPojo> workFlowPojoList = new ArrayList<>();
                proDetailHandlerHelp.handelDetailWorkFlow(businessType, paasFormDataEntityExt, workFlowPojoList, changeDocumentStatusSaveDTO.getLoginUser());
                changeDocumentStatusSaveVO.setWorkFlowPojoList(workFlowPojoList);
            }
        } catch (Exception e) {
            LOG.error("purchaseServiceImpl.changeDocumentStatus 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return changeDocumentStatusSaveVO;
    }

    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        PurchaseUpdateBatchDTO purchaseUpdateBatchDTO = new PurchaseUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO, purchaseUpdateBatchDTO);
        List<PurchaseUpdateDTO> purchaseList = new ArrayList<>();
        addBatchList.forEach(item ->{
            PurchaseUpdateDTO purchaseUpdateDTO = new PurchaseUpdateDTO();
            purchaseUpdateDTO.setData(item.getData());
            purchaseUpdateDTO.setId(item.getId());
            purchaseList.add(purchaseUpdateDTO);
        });
        purchaseUpdateBatchDTO.setPurchaseList(purchaseList);
        updateBatch(purchaseUpdateBatchDTO);

    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity paasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        // 团队保存
        teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), paasFormDataEntity.getId(), paasFormDataEntity, saasFormSaveDTO.getIsImport(), true);
//        userTeamService.saveUserTeam(saasFormSaveDTO);

        PurchaseEntityExt purchaseEntityExt = new PurchaseEntityExt();
        BeanUtil.copyProperties(paasFormDataEntity, purchaseEntityExt);
        Integer taskType = saasFormSaveDTO.getTaskType();
        Runnable runnable = () -> {
            try {
                // 保存要处理的关联产品和采购合同入库信息
                if (saasFormSaveDTO.getIsNew() || saasFormSaveDTO.getSaasNeedRedundantAttrPoJo().getAttrCanSee(PurchaseEnum.PRODUCT.getAttr())) {
                    dealWithPurchaseProduct(purchaseEntityExt, saasFormSaveDTO.getIsNew(),taskType);
                }
            } catch (Exception e) {
                LOG.error("采购合同保存产品数据解析/采购合同保存产品关联产品", e);
            }
        };
        threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity paasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        // 团队保存
        teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), paasFormDataEntity.getId(), paasFormDataEntity, saasFormSaveDTO.getIsImport(), true);
//        userTeamService.saveUserTeam(saasFormSaveDTO);

        PurchaseEntityExt purchaseEntityExt = new PurchaseEntityExt();
        BeanUtil.copyProperties(paasFormDataEntity, purchaseEntityExt);
        Integer taskType = saasFormSaveDTO.getTaskType();
        Runnable runnable = () -> {
            try {
                // 保存要处理的关联产品和采购合同入库信息
                if (saasFormSaveDTO.getIsNew() || saasFormSaveDTO.getSaasNeedRedundantAttrPoJo().getAttrCanSee(PurchaseEnum.PRODUCT.getAttr())) {
                    dealWithPurchaseProduct(purchaseEntityExt, saasFormSaveDTO.getIsNew(),taskType);
                }

            } catch (Exception e) {
                LOG.error("采购合同保存产品数据解析/采购合同保存产品关联产品", e);
            }
        };
        threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
    }
}
